Cod sursa(job #1695042)

Utilizator cosmin79Carabet Cosmin Andrei cosmin79 Data 26 aprilie 2016 14:47:06
Problema Andrei Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.96 kb
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cassert>
using namespace std;

class twoSatSolver {
private:
    int N;
    vector<vector<int>> G;
    vector<vector<int>> GT;

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

public:
    inline int negate(int node){
        return node > N ? node - N : node + N;
    }

    twoSatSolver(int _N) : N(_N) {
        G.assign(2 * N + 1, vector<int>());
        GT.assign(2 * N + 1, vector<int>());
    }

    void addOrEdge(int x, int y) {
        addEdge(negate(x), y);
        addEdge(negate(y), x);
    }

    void dfs1(int node, vector<bool>& mark, vector<int>& topoSort) {
        mark[node] = true;
        for (auto& x: G[node]) {
            if (!mark[x]) {
                dfs1(x, mark, topoSort);
            }
        }
        topoSort.push_back(node);
    }

    bool dfs2(int node, vector<bool>& mark, vector<bool>& sol) {
        if (sol[node]) {
            return false;
        }
        sol[negate(node)] = true;
        mark[node] = true;

        bool success = true;
        for (auto& x: GT[node]) {
            if (!mark[x]) {
                success &= dfs2(x, mark, sol);
            }
        }

        return success;
    }

    vector<bool> solve2SAT() {
        vector<bool> mark(2 * N + 1, false);
        vector<int> topoSort;
        topoSort.reserve(2 * N + 1);

        for (int i = 1; i <= 2 * N; i++) {
            if (!mark[i]) {
                dfs1(i, mark, topoSort);
            }
        }

        reverse(topoSort.begin(), topoSort.end());
        mark.assign(2 * N + 1, false);
        bool success = true;
        vector<bool> sol(2 * N + 1, false);

        for (auto& node: topoSort) {
            if (!mark[node] && !mark[negate(node)]) {
                success &= dfs2(node, mark, sol);
            }
        }

        assert(success);

        vector<bool> result(sol.begin(), sol.begin() + N + 1);
        return result;
    }
};
twoSatSolver* solver;

int N, M;
void read() {
    scanf("%d%d", &N, &M);
    solver = new twoSatSolver(N);

    int x, y, col;
    for (int i = 1; i <= M; i++) {
        scanf("%d%d%d", &x, &y, &col);
        switch (col) {
            case 0:
                // x | y
                solver -> addOrEdge(x, y);
                break;
            case 1:
                // ~x | ~y
                solver -> addOrEdge(solver -> negate(x), solver -> negate(y));
                break;
            case 2:
                // x <-> y = (x -> y) ^ (y -> x) = (~x | y) ^ (~y | x)
                solver -> addOrEdge(solver -> negate(x), y);
                solver -> addOrEdge(solver -> negate(y), x);
                break;
        }
    }
}

void solve() {
    vector<bool> result = solver -> solve2SAT();
    for (int i = 1; i <= N; i++) {
        printf("%d ", result[i] ? 1 : 0);
    }
    printf("\n");
}

int main() {
    freopen("andrei.in", "r", stdin);
    freopen("andrei.out", "w", stdout);
    read();
    solve();
    return 0;
}