Cod sursa(job #1851198)

Utilizator andrei.arnautuAndi Arnautu andrei.arnautu Data 19 ianuarie 2017 14:41:13
Problema 2SAT Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.73 kb
/**
  *  Worg
  */
#include <stack>
#include <cstdio>
#include <vector>
#include <algorithm>

using std::min;
using std::stack;
using std::vector;

FILE *fin = freopen("2sat.in", "r", stdin);
FILE *fout = freopen("2sat.out", "w", stdout);

const int MAX_N = 1 + 100000;
const int MAX_NODES = (MAX_N << 1);

/*-------- Input data --------*/
int N, M;
int total_nodes;
/*-------- Graph data --------*/
vector< int > graph[MAX_NODES];

int index[MAX_NODES], lowlink[MAX_NODES], where[MAX_NODES];
int current_index = 1;

bool in_stack[MAX_NODES];
stack< int > my_stack;
vector< int > current_scc;
vector< vector<int> > scc_list;

int node_value[MAX_NODES];
/*-------- --------*/

int OppositeNode(int node) {
    if(node > N) {
        return node - N;
    } else {
        return node + N;
    }
}

void ReadInput() {
    scanf("%d%d", &N, &M);
    total_nodes = 2 * N;
    for(int i = 1; i <= M; i++) {
        int x, y; scanf("%d%d", &x, &y);
        x = (x < 0) ? (-x + N) : (x);
        y = (y < 0) ? (-y + N) : (y);
        graph[OppositeNode(x)].push_back(y);
        graph[OppositeNode(y)].push_back(x);
    }
}

void StrongConnect(int node) {
    // printf("%d\n", node);
    index[node] = lowlink[node] = current_index;  // Initializam datele pentru nodul curent
    current_index ++;
    my_stack.push(node); in_stack[node] = true;

    for(int next_node : graph[node]) {
        if(!index[next_node]) {
            StrongConnect(next_node);
            lowlink[node] = min(lowlink[node], lowlink[next_node]);
        } else if(in_stack[next_node]){
            lowlink[node] = min(lowlink[node], index[next_node]);
        }
    }

    if(lowlink[node] == index[node]) {  // Am dat peste o noua componenta tare conexa
        current_scc.clear();
        int current_node;
        do {
            current_node = my_stack.top(); my_stack.pop();
            in_stack[current_node] = false; current_scc.push_back(current_node);
            where[current_node] = (int)scc_list.size();
        }while(current_node != node);  // Continuam pana dam peste nodul tata
        scc_list.push_back(current_scc);
    }
}

void RunTarjan() {
    for(int i = 1; i <= total_nodes; i++) {
        if(!index[i]) {
            StrongConnect(i);
        }
    }
}

bool GiveValues() {
    bool possible = true;
    for(int i = 1; i <= total_nodes; i++) {
        if(where[i] == where[OppositeNode(i)]) {
            possible = false; // Daca un nod si negatia lui sunt in aceeasi componenta, atunci nu avem solutie
        }
        node_value[i] = -1;
    }

    for(vector< int > scc : scc_list) {
        bool ok = true;
        for(int node : scc) {
            if(node_value[node] == 0) {
                ok = false; break;
            }
        }
        if(ok) {  // Putem face toate nodurile din componenta curenta sa aiba valoarea 1, iar opusele valoarea 0
            for(int node : scc) {
                node_value[node] = 1;
                node_value[OppositeNode(node)] = 0;
            }
        } else {  // Altfel facem toate nodurile sa aiba valoarea 0
            for(int node : scc) {
                node_value[node] = 0;
            }
        }
    }

    return possible;
}

void WriteOutput() {
    for(int i = 1; i <= N; i++) {
        printf("%d ", node_value[i]);
    }
}

void OutputSccList() {
    for(vector< int > scc : scc_list) {
        for(int node : scc) {
            printf("%d %d;", node, where[node]);
        }
        printf("\n");
    }
}

int main() {
    ReadInput();
    RunTarjan();
    // OutputSccList();            /** CAREFUL ! */
    if(GiveValues()) {
        WriteOutput();
    } else {
        printf("-1\n");
    }
    return 0;
}