Cod sursa(job #2011425)

Utilizator retrogradLucian Bicsi retrograd Data 16 august 2017 03:07:50
Problema 2SAT Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.22 kb
#include <bits/stdc++.h>

using namespace std;

/**
 * 2SAT Solver
 *
 * Usage:
 *
 * Add edges with AddEdge(u, v)
 * where u < 0 if not |u| and u > 0 if |u|
 * (edges are of type u -> v), and call Solve().
 *
 * Compute the answer by doing Solve()
 *  - if there is no answer, return value will be empty
 *
 * Also, keep in mind the 1-indexing of literals!
 **/
class TwoSAT {
    struct Node {
        vector<int> leg, gel;
        bool vis, is_true;
    };
    vector<Node> T;
    vector<bool> sol;
    vector<int> stk;
    bool no_sol;
    int n;

    void dfs_forward(int node) {
        T[node].vis = true;

        for (auto vec : T[node].leg)
            if (!T[vec].vis)
                dfs_forward(vec);

        stk.push_back(node);
    }

    void dfs_backward(int node) {
        T[node].vis = false;

        // Set node's truth value to false
        if (T[node].is_true) no_sol = true;
        T[node ^ 1].is_true = true;

        sol[node / 2] = ((node & 1) ^ 1);

        // Whatever implies false is false
        for (auto vec : T[node].gel)
            if (T[vec].vis) 
                dfs_backward(vec);
    }

    int get_node(int x) {
        if (x > 0) return 2 * (x - 1) + 1;
        return 2 * (-x - 1);
    }

public:
    TwoSAT(int n) : T(2 * n), sol(n, 0), n(n) {
        stk.reserve(2 * n);
    }

    void AddEdge(int a, int b) {
        a = get_node(a); b = get_node(b);
        T[a].leg.push_back(b);
        T[b].gel.push_back(a);
    }

    vector<bool> Solve() {
        for(int i = 0; i < 2 * n; ++i)
            if (!T[i].vis)
                dfs_forward(i);

        no_sol = false;

        for (int i = 2 * n - 1; i >= 0; --i) {
            if (T[stk[i]].vis && T[stk[i] ^ 1].vis)
                dfs_backward(stk[i]);
        }

        return no_sol ? vector<bool>() : sol;
    }
};

int main() {
    freopen("2sat.in", "r", stdin);
    freopen("2sat.out", "w", stdout);
 
    int n, m; cin >> n >> m;
    TwoSAT sat(n);
    while (m--) {
        int a, b; cin >> a >> b;
        sat.AddEdge(-a, b);
        sat.AddEdge(-b, a);
    }
 
    auto ret = sat.Solve();
    if (ret.empty()) {
        cout << -1 << endl;
    } else {
        for (auto x : ret)
            cout << x << " ";
        cout << endl;
    }

    return 0;
}