Cod sursa(job #517550)

Utilizator AndreyPAndrei Poenaru AndreyP Data 29 decembrie 2010 09:59:28
Problema Party Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.78 kb
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <bitset>
#include <stack>
using namespace std;
#define N 210
#define pb push_back

int n,n1,nc;
vector< int > a[N],b[N],bt[N];
vector< vector <int> > c;
int ind[N],indlow[N],indice;
int com[N];
bitset< N > inst,rez;
stack< int > st;
int deg[N];

template< class T>
inline T minim(T x,T y) {
	return ( (x<y) ? x : y);
}


inline int no(int x) {
	return ( (x<=n1) ? (x+n1) : (x-n1) );
}

inline void citire() {
	int m,x,y,z;
	scanf("%d%d",&n1,&m);
	n = n1<<1;

	for(int i=0; i<m; ++i) {
		scanf("%d%d%d",&x,&y,&z);
		if(z==0) {
			a[no(x)].pb(y);
			a[no(y)].pb(x);
			continue;
		}
		if(z==1) {
			a[no(x)].pb(no(y));
			continue;
		}
		if(z==2) {
			a[no(y)].pb(no(x));
			continue;
		}
		if(z==3) {
			a[x].pb(no(y));
			a[y].pb(no(x));
			continue;
		}
	}
}

void tarjan(int nod) {
	ind[nod] = indlow[nod] = (++indice);
	st.push(nod);
	inst[nod] = 1;

	int nod1;
	for(size_t i=0,lim=a[nod].size(); i<lim; ++i) {
		nod1 = a[nod][i];
		if(ind[nod1]==0) {
			tarjan(nod1);
			indlow[nod] = minim(indlow[nod],indlow[nod1]);
		} else
		if(inst[nod1]==1)
			indlow[nod] = minim(indlow[nod],indlow[nod1]);
	}

	if(ind[nod]==indlow[nod]) {
		++nc;
		c.resize(nc+1);
		do {
			nod1 = st.top();
			st.pop();
			c[nc].pb(nod1);
			com[nod1] = nc;
			inst[nod1] = 0;
		}while(nod!=nod1);
	}
}

inline void comprima() {
	int aux,nod;
	for(int i=1; i<=nc; ++i) {
		inst.reset();
		inst[i] = 1;
		for(size_t j=0,lim=c[i].size(); j<lim; ++j) {
			nod = c[i][j];
			for(size_t t=0,lim1=a[nod].size(); t<lim1; ++t) {
				aux = com[a[nod][t]];
				if(inst[aux]==1)
					continue;
				inst[aux] = 1;
				b[i].pb(aux);
				++deg[aux];
			}
		}
	}
}

inline void rezolva() {
	ind[0] = 0;
	inst.reset();
	for(int i=1; i<=nc; ++i) {
		if(deg[i]==0)
			ind[++ind[0]] = i;
	}

	int nod;
	for(int i=1; i<=ind[0]; ++i) {
		nod = ind[i];
		for(size_t j=0,lim=b[nod].size(); j<lim; ++j) {
			--deg[b[nod][j]];
			if(deg[b[nod][j]]==0)
				ind[++ind[0]] = b[nod][j];
		}
	}

	int i=1;
	if(nc%2==1)
		for(;;);
	for(int k=nc>>1; k>0; --k) {
		for(; i<=ind[0] && inst[ind[i]]==1; ++i)
			;
		nod = ind[i];
		rez[nod] = 0;
		rez[com[no(c[nod].front())]] = 1;
		inst[nod] = 1;
		inst[com[no(c[nod].front())]] = 1;
	}
}

inline void criza() {
	for(int i=1; i<=nc; ++i) {
		for(size_t j=0,lim=b[i].size(); j<lim; ++j)
			bt[b[i][j]].pb(i);
	}

	int nod,nod1;
	bool ok;
	for(int i=1; i<=nc; ++i) {
		if(c[i].front()>n1)
			continue;
		nod = i;
		nod1 = com[no(c[nod].front())];
		rez[nod] = 1;
		rez[nod1] = 0;

		ok = true;
		for(size_t j=0,lim=b[nod].size(); j<lim && ok; ++j) {
			if(rez[b[nod][j]]==0)
				ok = false;
		}
		for(size_t j=0,lim=bt[nod1].size(); j<lim && ok;++j) {
			if(rez[bt[nod1][j]]==1)
				ok = false;
		}
		
		if(ok) {
			printf("%d\n",c[nod].size());
			for(size_t j=0,lim=c[nod].size(); j<lim; ++j)
				printf("%d\n",c[nod][j]);
			return;
		} else {
			rez[nod] = 0;
			rez[nod1] = 1;
		}
	}
}

inline void verif() {
	for(int i=1; i<=n; ++i) {
		if(rez[com[i]]==0)
			continue;
		for(size_t j=0,lim=a[i].size(); j<lim; ++j) {
			if(rez[com[a[i][j]]]==0)
				exit(4);
		}
	}
}

inline void scrie() {
	int nrez = 0;
	for(int i=1; i<=n1; ++i) {
		if(rez[com[i]]==1)
			++nrez;
	}

	if(nrez==0) {
		criza();
		return;
	}

	verif();
	printf("%d\n",nrez);
	for(int i=1; i<=n1; ++i) {
		if(rez[com[i]]==1)
			printf("%d\n",i);
	}
}

int main() {
	freopen("party.in","r",stdin);
	freopen("party.out","w",stdout);

	citire();
	for(int i=1; i<=n; ++i) {
		if(ind[i]==0)
			tarjan(i);
	}
	for(int i=1; i<=n1; ++i) {
		if(com[i]==com[i+n1])
			exit(4);
	}
	comprima();
	rezolva();
	scrie();

	return 0;
}