Cod sursa(job #2042274)

Utilizator Impaler_009Mihai Nitu Impaler_009 Data 18 octombrie 2017 12:06:55
Problema 2SAT Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.5 kb
#include <iostream>
#include <vector>
#include <stack>

using namespace std;

class TarjanSCC {
    int n;
    vector<vector<int>> G, sccs;
    vector<int> wh, ind, lowlink;
    stack<int> st;
    vector<bool> inStack;
    int indCount;

    void Dfs(int x) {
        ind[x] = ++indCount;
        lowlink[x] = ind[x];
        st.push(x);
        inStack[x] = true;

        for (auto y : G[x]) {
            if (!ind[y] || inStack[y]) {
                if (!ind[y])
                    Dfs(y);
                lowlink[x] = min(lowlink[x], lowlink[y]);
            }
        }

        if (lowlink[x] == ind[x]) {
            vector<int> scc;
            int y;
            do {
                y = st.top();
                st.pop();
                inStack[y] = false;
                wh[y] = sccs.size();
                scc.push_back(y);
            } while(y != x);
            sccs.push_back(scc);
        }
    }

  public:
    TarjanSCC(const vector<vector<int>>& G) : G(G) {
        n = G.size() - 1;
        wh = ind = lowlink = vector<int>(n+1);
        inStack = vector<bool>(n+1);
        indCount = 0;

        for (int i = 1; i <= n; ++i) {
            if (!ind[i]) {
                Dfs(i);
            }
        }
    }

    vector<vector<int>> GetSCCs() {
        return sccs;
    }

    vector<int> GetWh() {
        return wh;
    }
};

class TwoSAT {
    // Number of variables.
    int n;
    // Private representation of graph.
    vector<vector<int>> G;
    // Index of zero in private representation.
    const int zero;

    // Public representation to private representation.
    int ind(int x) {
        return x > 0 ? ((x << 1) + 1) : (((-x) << 1) + 2);
    }

    // Oposite of private representation.
    int op(int x) {
        return (x&1) ? x + 1 : x - 1;
    }

    // Resize structure to fit n variables.
    void Resize(int n) {
        if (n > this->n) {
            this->n = n;
            G.resize(max(ind(n), ind(-n)) + 1);
        }
    }

    void AddEdge(int x, int y) {
        G[x].push_back(y);
        G[op(y)].push_back(op(x));
    }

  public:
    void Implication(int x, int y) {
        Resize(max(abs(x), abs(y)));
        AddEdge(ind(x), ind(y));
    }

    void Disjunction(int x, int y) {
        Resize(max(abs(x), abs(y)));
        AddEdge(ind(-x), ind(y));
    }

    void SetToZero(int x) {
        Resize(abs(x));
        AddEdge(ind(x), zero);
    }

    void SetToOne(int x) {
        Resize(abs(x));
        AddEdge(op(zero), ind(x));
    }

    TwoSAT(int n=0) : n(n), zero(1) {
        G.resize(2*n + 3);
        // Edge from zero to op(zero) ensures its value will be zero.
        AddEdge(zero, op(zero));
    }

    vector<bool> Solve() {
        TarjanSCC sccSolver(G);
        auto wh = sccSolver.GetWh();

        if (wh[zero] == wh[op(zero)])
            return {};

        for (int i = 1; i <= n; ++i) {
            if (wh[ind(i)] == wh[op(ind(i))])
                return {};
        }

        vector<bool> sol(n+1);
        for (int i = 1; i <= n; ++i) {
            sol[i] = (wh[ind(i)] > wh[op(ind(i))] ? 0 : 1);
        }

        return sol;
    }
};

int main() {
    freopen("2sat.in", "r", stdin);
    freopen("2sat.out", "w", stdout);
    int n, m;
    cin >> n >> m;

    TwoSAT solver(n);

    for (int i = 1; i <= m; ++i) {
        int a, b;
        cin >> a >> b;

        solver.Disjunction(a, b);
    }

    auto sol = solver.Solve();

    if (sol.empty()) {
        cout << -1 << "\n";
    } else {
        for (int i = 1; i <= n; ++i) {
            cout << sol[i] << " ";
        }
    }
}