Cod sursa(job #688670)

Utilizator PetcuIoanPetcu Ioan Vlad PetcuIoan Data 23 februarie 2012 18:53:07
Problema 2SAT Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.31 kb
#include<stdio.h>
#include<assert.h>

#include<vector>
#include<algorithm>

using namespace std;

const int kvert = 200010;
vector<int> graph[kvert], graph_con[kvert];
vector< vector<int> > str_con;
vector<int> stack;
int n, m, k, exists = 1, index, instack[kvert], vis[kvert], v_index[kvert], v_lowlink[kvert], sol[kvert/2], vals[kvert];
int incon[kvert], gradver[kvert];

int deny(int x){
    if(x > n)
        return x - n;
    return x + n;
}

void read(){
    assert(freopen("2sat.in","r",stdin)!=NULL);
    scanf("%d%d",&n ,&m);
    k = 2 * n;
    int x, y;
    for(int i = 1; i <= m; ++i){
        scanf("%d%d",&x ,&y);
        graph[deny(x)].push_back(y);
        graph[deny(y)].push_back(x);
    }
}

void dfs(int x){
    vis[x] = 1;
    stack.push_back(x);
    instack[x] = 1;
    v_index[x] = index;
    ++index;
    v_lowlink[x] = v_index[x];
    for(int i = 0; i < graph[x].size(); ++i)
        if(vis[graph[x][i]]){
            dfs(graph[x][i]);
            v_lowlink[x] = min(v_lowlink[x], v_lowlink[graph[x][i]]);
        }
        else if(instack[graph[x][i]])
            v_lowlink[x] = min(v_lowlink[x], v_lowlink[graph[x][i]]);
    if(v_lowlink[x] == v_index[x]){
        vector<int> aux;
        while(stack.back() != x){
            instack[stack.back()] = 0;
            aux.push_back(stack.back());
            stack.pop_back();
        }
        instack[x] = 0;
        aux.push_back(x);
        stack.pop_back();
        str_con.push_back(aux);
        aux.clear();
    }
}

void get_str_con(){
    int i;
    for(i = 1; i <= k; ++i)
        if(!vis[i])
            dfs(i);
}

void get_edges(int x, int y){
    for(int i = 0; i < graph[y].size(); ++i){
        graph_con[x].push_back(incon[graph[y][i]]);
        ++gradver[incon[graph[y][i]]];
    }
    graph[x].clear();
}

void compact_str_con(){
    int i, j;
    for(i = 0; i < str_con.size(); ++i)
        for(j = 0; j < str_con[i].size(); ++j){
            incon[str_con[i][j]] = i;
            get_edges(i, str_con[i][j]);
        }
    for(i = 1; i <= n; ++i)
        if(incon[i] == incon[deny(i)])
            exists = 0;
}

vector<int> queue;

void insert(int x){
    if(vals[x] != 0)
        return;
    vals[x] = 1;
    for(int i = 0; i < str_con[x].size(); ++i)
        vals[incon[deny(str_con[x][i])]] = -1;
    for(int i = 0; i < graph_con[x].size(); ++i){
        --gradver[graph_con[x][i]];
        if(gradver[graph_con[x][i]] == 0)
            queue.push_back(graph_con[x][i]);
    }
}

void sort_and_get_vals(){
    if(exists == 0)
        return ;

    for(int i = 0; i < str_con.size(); ++i)
        if(gradver[i] == 0)
            queue.push_back(i);
    int curent = 0;
    while(curent < queue.size()){
        insert(queue[curent]);
        ++curent;
    }
    for(int i = 0; i < str_con.size(); ++i)
        if(vals[i] == -1)
            vals[i] = 0;
}

void get_sol_from_vals(){
    if(exists == 0)
        return ;
    int i;
    for(i = n + 1; i <= k; ++i)
        sol[i - n] = vals[incon[i]];
}

void solve(){
    get_str_con();
    compact_str_con();
    sort_and_get_vals();
    get_sol_from_vals();
}

void write(){
    assert(freopen("2sat.out","w",stdout)!=NULL);
    int i;
    if(exists == 0){
        printf("-1");
        return ;
    }
    for(i = n + 1; i <= k; ++i)
        printf("%d ",sol[i - n]);
}

int main(){
    read();
    solve();
    write();
    return 0;
}