Cod sursa(job #487773)

Utilizator mihai_floreaFlorea Mihai Alexandru mihai_florea Data 26 septembrie 2010 15:21:53
Problema 2SAT Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.66 kb
#include <set>
#include <queue>
#include <vector>
#include <fstream>
using namespace std;

#define pb push_back

const int NMAX=100001;

vector<int> G[2*NMAX],GT[2*NMAX];
vector< vector<int> > CTC,H;
int N,M,NCTC,ctc[2*NMAX];

inline int c(int x) { return x>0 ? x : -x + N; }

void read()
{
	ifstream fin("2sat.in");
	int x,y;
	fin>>N>>M;
	while (M--)
	{
		fin>>x>>y;
		G[c(-x)].pb(c(y));
		G[c(-y)].pb(c(x));
		GT[c(y)].pb(c(-x));
		GT[c(x)].pb(c(-y));
	}
}

int parc[2*NMAX];
bool viz[2*NMAX];

void DF(int x)
{
	viz[x]=true;
	for (vector<int>::iterator it=G[x].begin();it!=G[x].end();++it)
		if (!viz[*it])
			DF(*it);
	parc[++parc[0]]=x;
}

void DFT(int x, vector<int> &v)
{
	viz[x]=true;
	v.pb(x);
	for (vector<int>::iterator it=GT[x].begin();it!=GT[x].end();++it)
		if (!viz[*it])
			DFT(*it, v);
}

void kosaraju()
{
	int i;
	for (i=1;i<=2*N;++i)
		if (!viz[i]) DF(i);

	for (i=1;i<=2*N;++i) viz[i]=false;

	for (i=2*N;i;--i)
	{
		if (viz[parc[i]]) continue;
		vector<int> tmp;
		DFT(parc[i], tmp);
		++NCTC;
		CTC.pb(tmp);
		for (vector<int>::iterator it=tmp.begin();it!=tmp.end();++it)
			ctc[*it]=NCTC-1;
	}
}

int deg[2*NMAX];

void buildH()
{
	H.resize(NCTC);

	for (int i=0;i<NCTC;++i)
	{
		set<int> S;
		S.insert(i);
		for (vector<int>::iterator k=CTC[i].begin();k!=CTC[i].end();++k)
			for (vector<int>::iterator it=G[*k].begin();it!=G[*k].end();++it)
				if (S.find(ctc[*it]) == S.end())
					H[i].pb(ctc[*it]), S.insert(ctc[*it]), ++deg[ctc[*it]];
	}
}

void sort_topo()
{
	queue<int> Q;
	for (int i=0;i<NCTC;++i) 
		if (deg[i]==0) Q.push(i);

	parc[0]=0;
	while (!Q.empty())
	{
		int x=Q.front();
		Q.pop();
		parc[++parc[0]]=x;
		for (vector<int>::iterator it=H[x].begin();it!=H[x].end();++it)
		{
			if (deg[*it]==0) continue;
			--deg[*it];
			if (deg[*it]==0) Q.push(*it);
		}
	}
}

int sol[NMAX];

void solve_2SAT()
{
	ofstream fout("2sat.out");
	for (int i=1;i<=N;++i)
		if (ctc[i] == ctc[c(-i)])
		{
			fout<<"-1\n";
			return;
		}

	for (int i=0;i<NCTC;++i) viz[i]=false;

	for (int i=1;i<=NCTC;++i)
	{
		int x=parc[i];
		if (viz[x]) continue;
		for (vector<int>::iterator it=CTC[x].begin();it!=CTC[x].end();++it)
			if (*it <= N) sol[*it]=0;
			else sol[*it - N]=1;
		int ret=CTC[x].back();
		if (ret <= N) ret+=N;
		else ret-=N;
		ret=ctc[ret];
		for (vector<int>::iterator it=CTC[ret].begin();it!=CTC[ret].end();++it)
			if (*it <= N) sol[*it]=1;
			else sol[*it - N]=0;
		viz[x]=viz[ret]=true;
	}

	for (int i=1;i<=N;++i)
		fout<<sol[i]<<" ";
}

int main()
{
	read();
	kosaraju();
	buildH();
	sort_topo();
	solve_2SAT();

	return 0;
}