Cod sursa(job #2447361)

Utilizator AndreiStanescuAlloys Nokito AndreiStanescu Data 13 august 2019 00:36:19
Problema 2SAT Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.53 kb
#include<vector>
#include<fstream>
#include<iostream>
#include<stack>
#include<queue>
#define N 100000
using namespace std;

int n,m,disc[N],low[N],In_stack[N],scc,comp[N],in_deg[N],val[N];
vector<int> G[N],sol[N];
stack<int> S;

void read()
{
    int x,y;
    ifstream fin("2sat.in");
    fin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        fin>>x>>y;
        if(x>0 && y>0)
        {G[x+n].push_back(y);
        G[y+n].push_back(x);
        }
        else
            if(x>0 && y<0)
        {
            G[x+n].push_back(n-y);
            G[-y].push_back(x);
        }
        else
            if(x<0 && y>0)
        {
            G[-x].push_back(y);
            G[y+n].push_back(n-x);
        }
        else
        {
            G[-x].push_back(n-y);
            G[-y].push_back(n-x);

        }
    }
    fin.close();
}


void Tarjan(int u,int &time)
{
    disc[u]=low[u]=++time;
    S.push(u);
    In_stack[u]=1;
    vector<int>::iterator it;
    for(it=G[u].begin();it!=G[u].end();it++)
    {
        int v=*it;
        if(!disc[v])
        {
            Tarjan(v,time);
            low[u]=min(low[u],low[v]);
        }
        else
            if(In_stack[v])
                low[u]=min(low[u],disc[v]);
    }

    if(low[u]==disc[u])
    {
        int w=0;
        ++scc;
        while(S.top()!=u)
        {
            sol[scc].push_back(S.top());
            In_stack[S.top()]=0;
            comp[S.top()]=scc;
            S.pop();
        }
        sol[scc].push_back(u);
        comp[u]=scc;
        In_stack[u]=0;
        S.pop();
    }


}

queue<int> q;

void solve()
{
    int start=0,satisfiable=1,x;
    for(int i=1;i<=2*n;i++)
        if(!disc[i])
        Tarjan(i,start);
    for(int i=1;i<=n && satisfiable;i++)
    if(comp[i]==comp[i+n])
        satisfiable=0;
    for(int i=1;i<=n;i++)
        val[i]=-1;
    //Toate nodurile dintr-o componenta tare-conexa au aceeasi valoare de adevar
    ofstream fout("2sat.out");
    if(satisfiable)
    {
        for(int i=1;i<=2*n;i++)
        {
            vector<int>::iterator it;
            for(it=G[i].begin();it!=G[i].end();it++)
                if(comp[i]!=comp[*it])
                in_deg[comp[*it]]++;
        }
        //Algoritmul lui Tarjan realizeaza o sortare topologica in ordine inversa,deci ultima
        //componenta tare conexa va avea gradul interior asociat 0
        for(int i=1;i<=scc;i++)
            if(!in_deg[i])
            q.push(i);
        //cout<<q.front();
        while(!q.empty())
        {
            x=q.front();
            q.pop();
            vector<int>::iterator it,it2;
            for(it=sol[x].begin();it!=sol[x].end();it++)
            {
                int change=((*it)>n )? (*it)-n : *it;
                if(val[change]==-1)
              {
                  //cout<<(*it)<<' ';
                  if((*it)>n)
                    val[change]=1;
                else
                    val[change]=0;
              }
            }

            for(it=sol[x].begin();it!=sol[x].end();it++)
                for(it2=G[*it].begin();it2!=G[*it].end();it2++)
            {
                if(comp[*it2]!=comp[*it])
                {
                    --in_deg[comp[*it2]];
                    if(in_deg[*it2]==0) q.push(comp[*it2]);
                }
            }


        }
        for(int i=1;i<=n;i++)
            fout<<val[i]<<' ';

    }
    else
        fout<<"-1";
    fout.close();

}



int main()
{
    read();
    solve();
}