Cod sursa(job #1543083)

Utilizator danny794Dan Danaila danny794 Data 5 decembrie 2015 22:08:24
Problema 2SAT Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.28 kb
#include <bitset>
#include <cstdio>
#include <vector>

#define NMAX (2 * 100000 + 1)
#define INF (1 << 30)

using namespace std;

int n, m;
bitset<NMAX> deg;
bitset<NMAX> solution;
bitset<NMAX> onStack;
vector<int> children[NMAX], stack;
vector<vector<int> > components, componentsEdges;
int minim[NMAX], index[NMAX], count;

inline int getIndex(int index) {
  return index > 0 ? index : n - index;
}

void readInput() {
  int a, b;
  freopen("2sat.in", "r", stdin);
  freopen("2sat.out", "w", stdout);
  scanf("%d %d\n", &n, &m);
  for (int i = 0; i < m; i++) {
    scanf("%d %d\n", &a, &b);
    children[getIndex(-a)].push_back(getIndex(b));
    deg[getIndex(b)] = 1;
    children[getIndex(-b)].push_back(getIndex(a));
    deg[getIndex(a)] = 1;
  }
  fclose(stdin);
  for (int i = 1; i <= 2 * n; i++) {
    index[i] = INF;
  }
}

void push(int idx) {
  onStack[idx] = 1;
  minim[idx] = index[idx] = ++count;
  stack.push_back(idx);
}

void pop(int idx) {
  if (minim[idx] == index[idx]) {
    components.push_back(vector<int>());
    componentsEdges.push_back(vector<int>());
    int top;
    do {
      top = stack.back();
      stack.pop_back();
      onStack[top] = 0;
      components.back().push_back(top);
    } while (top != idx);
  }
}

void visit(int idx) {
  push(idx);
  for (size_t i = 0; i < children[idx].size(); i++) {
    int child = children[idx][i];
    if (index[child] == INF) {
      visit(child);
      minim[idx] = min(minim[idx], minim[child]);
    } else if (onStack[child]) {
      minim[idx] = min(minim[idx], index[child]);
    }
  }
  pop(idx);
}

void getConnectedComponents() {
  for (int i = 1; i <= 2 * n; i++) {
    if (!deg[i]) {
      visit(i);
    }
  }
  for (int i = 1; i <= 2 * n; i++) {
    if (index[i] == INF) {
      visit(i);
    }
  }
  for (size_t i = 0; i < components.size(); i++) {
    for (size_t j = 0; j < components[i].size(); j++) {
      minim[components[i][j]] = i;
    }
  }
  for (int i = 1; i <= 2 * n; i++) {
    int a = minim[i];
    for (size_t j = 0; j < children[i].size(); j++) {
      int b = minim[children[i][j]];
      if (a != b) {
        componentsEdges[a].push_back(b);
      }
    }
  }
}

inline bool markNode(int node, int val) {
  if (onStack[node]) {
    return false;
  }
  onStack[node] = 1;
  solution[node] = val;
  return true;
}

int visitChildren(int idx) {
  int nodeValue = 1;
  for (size_t i = 0; i < componentsEdges[idx].size(); i++) {
    int child = componentsEdges[idx][i];
    child = components[child][0];
    if (onStack[child]) {
      if (!solution[child]) {
        nodeValue = 0;
      }
    } else {
      if (!visitChildren(child)) {
        nodeValue = 0;
      }
    }
  }
  return nodeValue;
}

bool solve() {
  for (size_t i = 0; i < components.size(); i++) {
    if (onStack[components[i][0]]) {
        continue;
    }
    int val = visitChildren(i);
    for (size_t j = 0; j < components[i].size(); j++) {
      int node = components[i][j];
      if (!markNode(node, val)) {
        return false;
      }
      node = node > n ? node - n : node + n;
      if (!markNode(node, 1 - val)) {
        return false;
      }
    }
  }
  return true;
}

int main() {
  readInput();
  getConnectedComponents();
  if (!solve()) {
    printf("-1\n");
  } else {
    for (int i = 1; i <= n; i++) {
      printf("%d ", solution[i] ? 1 : 0);
    }
  }
  return 0;
}