Cod sursa(job #2672812)

Utilizator vlad.ulmeanu30Ulmeanu Vlad vlad.ulmeanu30 Data 14 noiembrie 2020 22:17:28
Problema 2SAT Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.07 kb
#include <bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pli pair<ll,int>
#define pil pair<int,ll>
#define fi first
#define se second
#define inf (INT_MAX/2-1)
#define infl (1LL<<60)
#define vi vector<int>
#define vl vector<ll>
#define pb push_back
#define sz(a) (int)(a).size()
#define all(a) begin(a),end(a)
#define y0 y5656
#define y1 y7878
#define aaa system("pause");
#define dbg(x) cerr<<(#x)<<": "<<(x)<<'\n',aaa
#define dbga(x,n) cerr<<(#x)<<"[]: ";for(int _=0;_<n;_++)cerr<<x[_]<<' ';cerr<<'\n',aaa
#define dbgs(x) cerr<<(#x)<<"[stl]: ";for(auto _:x)cerr<<_<<' ';cerr<<'\n',aaa
#define dbgp(x) cerr<<(#x)<<": "<<x.fi<<' '<<x.se<<'\n',aaa
#define maxn 100000
#define maxm 200000

using namespace std;

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

vi g[2*maxm+5], gt[2*maxm+5], gn[2*maxm+5];
int indeg[2*maxm+5], v[2*maxm+5]; ///indeg = doar pt gn, v = valorile nodurilor
int comp[2*maxm+5]; ///comp = din ce ctc face parte ???
bool viz[2*maxm+5];

void ad (int x, int y) {
  g[x].pb(y);
  gt[y].pb(x);
}

int oth (int m, int x) {
  if (x <= m) return x+m;
  return x-m;
}

///trebuie sa scap de "cicli" sau componente tare conexe unde nu am nod cu indeg == 0.
///toate nodurile dintr-o ctc au aceeasi valoare. ulterior, dupa unificarea tuturor
///ctc-urilor in cate un singur nod fiecare, voi ramane cu un DAG, pe care pot face
///sortare topologica
vector<vi> ctc (int m) { ///returneaza vectori de componente
  vi preord;
  int i;
  function<void(int)> df = [&] (int nod) {
    viz[nod] = 1;
    for (int nn: g[nod])
      if (!viz[nn]) df(nn);
    preord.pb(nod);
  };
  for (i = 1; i <= 2*m; i++)
    if (!viz[i]) df(i);
  fill(viz+1, viz+2*m+1, 0);
  int now = 1;
  vector<vi> ret(1);
  function<void(int)> dft = [&] (int nod) {
    viz[nod] = 1;
    ret.back().pb(nod);
    comp[nod] = now;
    for (int nn: gt[nod])
      if (!viz[nn]) dft(nn);
  };
  for (i = 2*m-1; i >= 0; i--)
    if (!viz[preord[i]]) {
      ret.pb(vi());
      dft(preord[i]);
      now++;
    }
  return ret;
}

int main () {
  int n, m; fin >> m >> n;
  int i, a, b;
  vector<pii> input;
  for (i = 1; i <= n; i++) {
    fin >> a >> b;
    input.pb(pii(0, a));
    if (a < 0) input.back().fi = 1;
    input.pb(pii(0, b));
    if (b < 0) input.back().fi = 1;
    if (a > 0 && b > 0) {
      ad(m+a, b); ///!a => b
      ad(m+b, a); ///!b => a
    } else if (a > 0 && b < 0) {
      ad(m+a, m+abs(b)); ///!a => !b
      ad(abs(b), a); ///b => a
    } else if (a < 0 && b > 0) {
      ad(abs(a), b); ///a => b
      ad(m+b, m+abs(a)); ///!b => !a
    } else {
      ad(abs(a), m+abs(b)); ///a => !b
      ad(abs(b), m+abs(a)); ///b => !a
    }
  }
  vector<vi> div = ctc(m); ///div = diviziune graf in ctc
  int numc = sz(div)-1;
  for (i = 1; i <= 2*m; i++)
    for (int x: g[i])
      if (comp[i] != comp[x]) {
        gn[comp[i]].pb(comp[x]);
        indeg[comp[x]]++;
      }
  ///acum lucrezi pe gn
  queue<int> qu;
  for (i = 1; i <= numc; i++)
    if (indeg[i] == 0) qu.push(i);
  fill(v+1, v+2*m+1, -1);
  while (!qu.empty()) {
    int nod = qu.front(); qu.pop();
    for (int x: div[nod]) { ///pt fiecare nod efectiv din diviziune
      if (v[x] == -1) v[x] = 0;
      if (v[oth(m, x)] == -1) v[oth(m, x)] = 1;
    }
    for (int nn: gn[nod]) {
      indeg[nn]--;
      if (indeg[nn] == 0) qu.push(nn);
    }
  }
  for (i = 1; i <= 2*m; i++)
    if (v[i] == -1 && v[oth(m, i)] != -1) v[i] = v[oth(m, i)] ^ 1;
  for (i = 1; i <= 2*m; i++)
    if (v[i] == -1) v[i] = 0;
  bool ok = 1;
  for (i = 1; i <= n && ok; i++) {
    bool now = 0;
    if (input[(i-1)*2].fi == 0) now |= v[input[(i-1)*2].se];
    else now |= v[oth(m, input[(i-1)*2].se)];
    if (input[(i-1)*2+1].fi == 0) now |= v[input[(i-1)*2+1].se];
    else now |= v[oth(m, input[(i-1)*2+1].se)];
    ok &= now;
  }
  if (!ok) fout << -1;
  else for (i = 1; i <= m; i++) fout << v[i] << ' ';
  fin.close(); fout.close();
  return 0;
}
/**
3 4
+ 1 + 2
- 1 + 3
+ 4 - 2
3 3
+ 1 + 2
- 1 + 3
- 3 - 2
**/