Pagini recente » Cod sursa (job #894166) | Cod sursa (job #2947525) | Cod sursa (job #2252429) | Cod sursa (job #2118938) | Cod sursa (job #2352026)
#include <fstream>
#include <stack>
#include <vector>
using namespace std;
class Graph
{
public:
Graph(int size) : nodes_(vector<Node>(2 * size)) {}
int Vars() const { return nodes_.size() / 2; }
void AddClause(int a, int b);
friend class TwoSat;
private:
int GetRealNode(int math) const;
int GetMathNode(int real) const;
struct Node
{
vector<int> edges;
int comp = 0;
int time = 0;
int low = 0;
bool in_stack = false;
};
vector<Node> nodes_;
};
int Graph::GetRealNode(int math) const
{
if (math > 0) {
return math - 1;
}
return Vars() - math - 1;
}
int Graph::GetMathNode(int real) const
{
if (real < Vars()) {
return real + 1;
}
return -(real - Vars() + 1);
}
void Graph::AddClause(int a, int b)
{
auto real_a = GetRealNode(a);
auto real_b = GetRealNode(b);
auto not_a = GetRealNode(-a);
auto not_b = GetRealNode(-b);
nodes_[not_a].edges.push_back(real_b);
nodes_[not_b].edges.push_back(real_a);
}
class TwoSat
{
public:
static vector<bool> Solve(Graph &g);
private:
static vector<int> FindComps(Graph &g);
static void Dfs(Graph &g, int node, stack<int> &st, vector<int> &order);
static void ExtractComp(Graph &g, stack<int> &st, int node, vector<int> &order);
};
void TwoSat::ExtractComp(Graph &g, stack<int> &st, int node, vector<int> &order)
{
static auto next_comp = 0;
next_comp += 1;
while (order.empty() || order.back() != node) {
order.push_back(st.top());
g.nodes_[st.top()].comp = next_comp;
g.nodes_[st.top()].in_stack = false;
st.pop();
}
}
void TwoSat::Dfs(Graph &g, int node, stack<int> &st, vector<int> &order)
{
static auto time = 0;
g.nodes_[node].low = g.nodes_[node].time = (time += 1);
st.push(node);
g.nodes_[node].in_stack = true;
for (const auto &next : g.nodes_[node].edges) {
if (g.nodes_[next].time == 0) {
Dfs(g, next, st, order);
}
if (g.nodes_[next].in_stack) {
g.nodes_[node].low = min(g.nodes_[node].low, g.nodes_[next].low);
}
}
if (g.nodes_[node].low >= g.nodes_[node].time) {
ExtractComp(g, st, node, order);
}
}
vector<int> TwoSat::FindComps(Graph &g)
{
vector<int> order;
for (size_t i = 0; i < g.nodes_.size(); i += 1) {
if (g.nodes_[i].time == 0) {
stack<int> st;
Dfs(g, i, st, order);
}
}
return order;
}
vector<bool> TwoSat::Solve(Graph &g)
{
auto order = FindComps(g);
vector<bool> res(g.Vars(), false);
vector<bool> used(g.Vars(), false);
for (int i = order.size() - 1; i >= 0; i -= 1) {
auto real_node = order[i];
auto math_node = g.GetMathNode(real_node);
auto not_node = g.GetRealNode(-math_node);
if (g.nodes_[real_node].comp == g.nodes_[not_node].comp) {
return vector<bool>();
}
auto node = abs(math_node) - 1;
if (!used[node]) {
res[node] = (math_node > 0 ? false : true);
used[node] = true;
}
}
return res;
}
int main()
{
ifstream fin("2sat.in");
ofstream fout("2sat.out");
int vars, clauses;
fin >> vars >> clauses;
Graph graph(vars);
for (auto i = 0; i < clauses; i += 1) {
int a, b;
fin >> a >> b;
graph.AddClause(a, b);
}
auto res = TwoSat::Solve(graph);
if (res.empty()) {
fout << "-1\n";
return 0;
}
for (const auto &val : res) {
fout << val << " ";
}
fout << "\n";
return 0;
}