Cod sursa(job #1851203)

Utilizator andrei.arnautuAndi Arnautu andrei.arnautu Data 19 ianuarie 2017 14:52:05
Problema 2SAT Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.11 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, scc_index = 0;

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

int node_value[MAX_NODES];
bool valid_expression = true;
/*-------- --------*/

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 ProcessScc() {
    bool ok = true;
    for(int node : current_scc) {
        if(where[node] == where[OppositeNode(node)]) {
            valid_expression = false;
        }
        if(node_value[node] == false) {
            ok = false;
        }
    }

    for(int node : current_scc) {
        if(ok == true) {
            node_value[node] = true;
            node_value[OppositeNode(node)] = false;
        } else {
            node_value[node] = false;
        }
    }
}

void StrongConnect(int 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(); scc_index ++;
        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] = scc_index;
        }while(current_node != node);  // Continuam pana dam peste nodul tata

        ProcessScc();
    }
}

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

void WriteOutput() {
    if(valid_expression == true) {
        for(int i = 1; i <= N; i++) {
            printf("%d ", node_value[i]);
        }
    } else {
        printf("-1\n");
    }
}

int main() {
    ReadInput();
    RunTarjan();
    WriteOutput();
    return 0;
}