Cod sursa(job #826640)

Utilizator mihai995mihai995 mihai995 Data 30 noiembrie 2012 23:26:41
Problema 2SAT Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 5.64 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <stack>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 100005;

struct Ctc{
    bool etc1[2 * N], *use;
    int etc2[2 * N], *ctc;
    vector<int> *graph, *trans;
    vector<int> etc3[2 * N];
    stack<int> S;

    Ctc(){
        use = etc1 + N;
        ctc = etc2 + N;
        trans = etc3 + N;
    }

    void dfs(int x){
        use[x] = true;

        for (vector<int> :: iterator it = trans[x].begin() ; it != trans[x].end() ; it++)
            if (!use[*it])
                dfs(*it);

        S.push(x);
    }

    void dfs(int x, int C){
        ctc[x] = C;
        use[x] = true;

        for (vector<int> :: iterator it = graph[x].begin() ; it != graph[x].end() ; it++)
            if (!use[*it])
                dfs(*it, C);
    }

    void compute(int st, int dr){
        int nr = 0;

        for (int i = st ; i <= dr ; i++)
            for (vector<int> :: iterator it = graph[i].begin() ; it != graph[i].end() ; it++)
                trans[*it].push_back(i);

        memset(etc1, false, sizeof(etc1));

        use[0] = true;

        for (int i = st ; i <= dr ; i++)
            if (!use[i])
                dfs(i);

        memset(etc1, false, sizeof(etc1));

        use[0] = true;

        while (!S.empty()){
            if (!use[S.top()])
                dfs(S.top(), ++nr);

            S.pop();
        }
    }

    void get_data(vector<int> *_graph, int st, int dr){
        graph = _graph;

        compute(st, dr);
    }

    int* get_ctc(){
        return ctc;
    }
};

struct TopSort{
    vector<int>* graph;
    vector<int> ord;
    int need[2 * N], size;

    TopSort(vector<int>* v, int n){
        size = n;
        graph = v;
    }

    void dfs(int x){
        --need[x];
        ord.push_back(x);

        for (vector<int> :: iterator it = graph[x].begin() ; it != graph[x].end() ; it++)
            if (!(--need[*it]))
                dfs(*it);
    }

    void get_need(){
        for (int i = 1 ; i <= size ; i++)
            for (vector<int> :: iterator it = graph[i].begin() ; it != graph[i].end() ; it++)
                need[*it]++;
    }

    void compute(){
        get_need();

        for (int i = 1 ; i <= size ; i++)
            if (!need[i])
                dfs(i);
    }

    vector<int> top_sort(){
        compute();

        return ord;
    }
};

struct Sat{
    vector<int> etc1[2 * N], *graph;
    vector<int> tree[2 * N], negate[2 * N];
    int etc2[2 * N], *ctc;
    int val[2 * N], nrC, size;
    bool use[2 * N], okay;
    Ctc A;

    Sat(){
        graph = etc1 + N;
        ctc = etc2 + N;

        nrC = 0;
        okay = true;
    }

    void unalloc(vector<int>& v){
        vector<int> a;
        a.swap(v);
    }

    void push(int x, int y){
        graph[-x].push_back(y);
        graph[-y].push_back(x);
    }

    void copy(int* a, int* b){
        for (int i = -size ; i <= size ; i++)
            a[i] = b[i];
    }

    void add(vector<int>& tree, vector<int>& v, int x){
        for (vector<int> :: iterator it = v.begin() ; it != v.end() ; it++)
            if (ctc[*it] != x)
                tree.push_back(ctc[*it]);
    }

    void arrange(vector<int>& v){
        vector<int> a;

        sort(v.begin(), v.end());

        for (vector<int> :: iterator it = v.begin() ; it != v.end() ; it++)
            if (a.empty() || a.back() != *it)
                a.push_back(*it);

        v.swap(a);
    }

    void get_ctc(){

        A.get_data(graph, -size, size);

        copy(ctc, A.get_ctc());

        for (int i = -size ; i <= size ; i++)
            if (nrC < ctc[i])
                nrC = ctc[i];
    }

    void build_tree(){
        for (int i = -size ; i <= size ; i++)
            add(tree[ ctc[i] ], graph[i], ctc[i]);

        for (int i = 1 ; i <= nrC ; i++)
            arrange(tree[i]);
    }

    void dfs(int x, bool stts){
        if (use[x]){
            if (val[x] != stts)
                okay = false;
            return;
        }

        use[x] = true;
        val[x] = stts;

        for (vector<int> :: iterator it = negate[x].begin() ; it != negate[x].end() ; it++)
            dfs(*it, !stts);

        if (!stts)
            return;

        for (vector<int> :: iterator it = tree[x].begin() ; it != tree[x].end() ; it++)
            dfs(*it, stts);
    }

    vector<int> top_sort(){
        TopSort T(tree, size);

        return T.top_sort();
    }

    void compute(){
        get_ctc();

        build_tree();

        for (int i = 1 ; i <= size ; i++){
            negate[ ctc[i] ].push_back(ctc[-i]);
            negate[ ctc[-i] ].push_back(ctc[i]);
        }

        vector<int> v = top_sort();

        memset(use, false, sizeof(use));

        for (vector<int> :: iterator it = v.begin() ; it != v.end() ; it++)
            if (!use[*it])
                dfs(*it, false);
    }

    vector<int> get_sat(){
        compute();

        vector<int> v;

        if (!okay){
            v.push_back(-1);

            return v;
        }

        for (int i = 1 ; i <= size ; i++)
            v.push_back( val[ ctc[i] ] );

        return v;
    }
} S;

ifstream in("2sat.in");
ofstream out("2sat.out");

int main(){
    int m, x, y;

    in >> S.size >> m;

    while (m--){
        in >> x >> y;

        S.push(x, y);
    }

    vector<int> v = S.get_sat();

    for (vector<int> :: iterator it = v.begin() ; it != v.end() ; it++)
        out << (*it) << " ";

    out << "\n";

    return 0;
}