Pagini recente » Cod sursa (job #1750928) | Cod sursa (job #983819) | Cod sursa (job #823951) | Cod sursa (job #643821) | Cod sursa (job #2289729)
#include <fstream>
#include <queue>
#include <stack>
#include <vector>
using namespace std;
struct Node
{
vector<int> edges;
int time = -1;
int low = -1;
int comp = -1;
bool on_stack = false;
};
class TwoSat;
class Graph
{
public:
friend class TwoSat;
Graph(int vars)
: nodes_(vector<Node>(2 * vars + 1)),
vars_(vars) {}
void AddClause(int a, int b);
private:
vector<Node> nodes_;
int vars_;
int GetRealNode(int node) const;
int GetMathNode(int node) const;
};
int Graph::GetRealNode(int node) const
{
if (node > 0) {
return node;
}
return vars_ - node;
}
int Graph::GetMathNode(int node) const
{
if (node <= vars_) {
return node;
}
return vars_ - node;
}
void Graph::AddClause(int a, int b)
{
auto real_a = GetRealNode(a);
auto real_b = GetRealNode(b);
auto real_not_a = GetRealNode(-a);
auto real_not_b = GetRealNode(-b);
nodes_[real_not_a].edges.push_back(real_b);
nodes_[real_not_b].edges.push_back(real_a);
}
class TwoSat
{
public:
static vector<bool> FindSolution(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 last_node, vector<int> &order);
};
vector<bool> TwoSat::FindSolution(Graph &g)
{
vector<bool> sol(g.vars_, false);
vector<bool> is_set(g.vars_, false);
auto order = FindComps(g);
for (int i = 1; i <= g.vars_; i += 1) {
auto not_i = g.GetRealNode(-i);
if (g.nodes_[i].comp == g.nodes_[not_i].comp) {
return vector<bool>();
}
}
for (int i = order.size() - 1; i >= 0; i -= 1) {
auto node = g.GetMathNode(order[i]);
if (!is_set[abs(node) - 1]) {
sol[abs(node) - 1] = (node < 0);
is_set[abs(node) - 1] = true;
}
}
return sol;
}
vector<int> TwoSat::FindComps(Graph &g)
{
vector<int> order;
for (auto i = 1; i <= 2 * g.vars_; i += 1) {
if (g.nodes_[i].time == -1) {
stack<int> st;
Dfs(g, i, st, order);
}
}
return order;
}
void TwoSat::Dfs(Graph &g, int node, stack<int> &st, vector<int> &order)
{
auto &curr_node = g.nodes_[node];
static auto time = 0;
curr_node.time = curr_node.low = (time += 1);
st.push(node);
curr_node.on_stack = true;
for (const auto &next : curr_node.edges) {
auto &next_node = g.nodes_[next];
if (next_node.time == -1) {
Dfs(g, next, st, order);
}
if (next_node.on_stack) {
curr_node.low = min(curr_node.low, next_node.low);
}
}
if (curr_node.low >= curr_node.time) {
ExtractComp(g, st, node, order);
}
}
void TwoSat::ExtractComp(Graph &g, stack<int> &st,
int last_node, vector<int> &order)
{
static auto next_comp = 0;
next_comp += 1;
while (st.top() != last_node) {
g.nodes_[st.top()].comp = next_comp;
g.nodes_[st.top()].on_stack = false;
order.push_back(st.top());
st.pop();
}
g.nodes_[st.top()].comp = next_comp;
g.nodes_[st.top()].on_stack = false;
order.push_back(st.top());
st.pop();
}
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::FindSolution(graph);
if (res.empty()) {
fout << "-1\n";
} else {
for (const auto &val : res) {
fout << (val ? 1 : 0) << " ";
}
fout << "\n";
}
return 0;
}