3648

/*
2SAT,找出一组解
逆缩图序,拓扑排序,然后染色。
找出和新娘颜色相同的点
*/

// include file
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <ctime>

#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <bitset>
#include <strstream>

#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <set>
#include <list>
#include <functional>

using namespace std;

// typedef
typedef long long LL;
typedef unsigned long long ULL;

// 
#define read freopen("in.txt","r",stdin)
#define write freopen("out.txt","w",stdout)
#define FORi(a,b,c) for(int i=(a);i<(b);i+=c)
#define FORj(a,b,c) for(int j=(a);j<(b);j+=c)

#define FF(i,a)    for(int i=0;i<(a);i+++)
#define FFD(i,a)   for(int i=(a)-1;i>=0;i--)
#define Z(a) (a<<1)
#define Y(a) (a>>1)

const double eps = 1e-11;
const double Pi = acos(-1.0);

template<class T> inline T sqr(T a){return a*a;}
template<class T> inline T TMAX(T x,T y)
{
	if(x>y) return x;
	return y;
}
template<class T> inline T TMIN(T x,T y)
{
	if(x<y) return x;
	return y;
}
template<class T> inline void SWAP(T &x,T &y)
{
	T t = x;
	x = y;
	y = t;
}
template<class T> inline T MMAX(T x,T y,T z)
{
	return TMAX(TMAX(x,y),z);
}


// code begin
#define MAXN 200

vector<int> G[MAXN];
int NG[MAXN][MAXN];
int in[MAXN];
int col[MAXN];
vector<int> tp;
int link[MAXN];

int scc;
int cnt;
int used[MAXN];
int stk1[MAXN],top1;
int stk2[MAXN],top2;
int isin[MAXN];
int dfn[MAXN];
int low[MAXN];
int id[MAXN];
int N,M;

void gabow_scc(int i)
{
	used[i] = true;
	stk1[top1++] = i;
	stk2[top2++] = i;
	dfn[i] = cnt++;
	isin[i] = true;

	FORj( 0,G[i].size(),1 )
	{
		if(!used[ G[i][j] ])
		{
			gabow_scc(G[i][j]);
		}
		else if(isin[G[i][j]])
		{
			while(dfn[stk2[top2-1]]>dfn[G[i][j]])
				top2--;
		}
	}

	if(i==stk2[top2-1])
	{
		top2--;
		int w;
		do
		{
			w = stk1[--top1];
			isin[w] = false;
			id[w] = scc;
		}while(w!=i);

		scc++;
	}
}

void tarjan_scc(int i)
{
	used[i] = true;
	stk1[top1++] = i;
	dfn[i] = cnt;
	low[i] = cnt;
	cnt++;
	isin[i] = true;

	FORj(0,G[i].size(),1)
	{
		if(!used[ G[i][j] ])
		{
			tarjan_scc(G[i][j]);
			low[i] = TMIN(low[i],low[G[i][j]]);
		}
		else if(isin[G[i][j]])
		{
			low[i] = TMIN(low[i],dfn[G[i][j]]);
		}
	}

	if(dfn[i]==low[i])
	{
		int w;
		do
		{
			w=stk1[--top1];
			isin[w] = false;
			id[w] = scc;
		}while(w!=i);
		scc++;
	}
}

void dfs(int i)
{
	FORj(1,scc,1)
	{
		if( !col[j]&&NG[i][j] )
		{
			col[j]=2;
			dfs(j);
		}
	}
}

int getnum(char *ta)
{
	int n = strlen(ta);
	if(n==3)
	{
		return 2*( (ta[0]-'0')*10+ta[1]-'0' )+(ta[2]=='w'?0:1);
	}

		return 2*(ta[0]-'0')+(ta[1]=='w'?0:1);
}

int main()
{
	read;
	write;
	while(scanf("%d %d",&N,&M)!=-1)
	{
		if(N+M==0) break;
		FORi(0,N*4,1)
		{
			G[i].clear();
		}

		// 新娘和新郎有限制条件
		G[2*0+1].push_back(2*0);
		G[2*1].push_back(2*1+1);

		FORi(2,N*2,2)
		{
			// A xor B = 1;
			// i i+1
			G[2*i].push_back(2*(i+1)+1);
			G[2*(i+1)].push_back(2*i+1);

			G[2*(i+1)+1].push_back(2*i);
			G[2*i+1].push_back(2*(i+1));
		}

		// 通奸关系
		char s1[5],s3[5];
		while(M--)
		{
			scanf("%s %s",s1,s3);
			// 不能是1 1 
			int a = getnum(s1);
			int b = getnum(s3);
			
			if(a>b) SWAP(a,b);
			//printf("%d %d\n",a,b);
			if(a>1&&b>1)
			{
				G[2*a+1].push_back(2*b);
				G[2*b+1].push_back(2*a);
			}
			else if(a==1&&b>1)
			{
				G[2*b+1].push_back(2*b);
			}
			else if(a==0&&b>1)
			{
				//G[2*b+1].push_back(2*b);
			}
		}

		//
		memset(used,0,sizeof(used));
		memset(dfn,0,sizeof(dfn));
		memset(low,0,sizeof(low));
		memset(id,0,sizeof(id));
		scc = 1;
		cnt = 1;
		top1 = 0;

		FORi(0,4*N,1)
		{
			if(!used[i])
			{
				tarjan_scc(i);
			}
		}

		bool f = true;
		FORi(0,2*N,1)
		{
			if(id[2*i]==id[2*i+1])
			{
				f=false;
				break;
			}
		}
		if(f)
		{
			// 找一组方案
			FORi(1,scc,1)
			{
				FORj(1,scc,1)
					NG[i][j]=0;
			}
			memset(in,0,sizeof(in));
			FORi(0,4*N,1)
			{
				FORj(0,G[i].size(),1)
				{
					if( id[i]!=id[G[i][j]] )
					{
						NG[ id[G[i][j]] ][ id[i] ] = 1;
					}
				}
			}
			FORi(0,2*N,2)
			{
				//i i+1
				link[id[2*i]] = id[2*i+1];
				link[id[2*i+1]] = id[2*i];
				link[id[2*(i+1)]] = id[2*(i+1)+1];
				link[id[2*(i+1)+1]] = id[2*(i+1)];
			}

			//新图为NG
			tp.clear();
			queue<int> qi;
			FORi(1,scc,1)
			{
				FORj(1,scc,1)
				{
					if(i!=j && NG[i][j])
					{
						in[j]++;
					}
				}
			}
			FORi(1,scc,1)
			{
				if(in[i]==0)
				{
					qi.push(i);
				}
			}
			while(!qi.empty())
			{
				int cur = qi.front();
				qi.pop();

				tp.push_back(cur);

				FORi(1,scc,1)
				{
					if(cur!=i && NG[cur][i])
					{
						in[i]--;
						if(in[i]==0)
							qi.push(i);
					}
				}
			}
			
			//printf("scc:%d tp:%d\n",scc,tp.size());

			// 排序后
			memset(col,0,sizeof(col));
			FORi(0,tp.size(),1)
			{
				if(!col[tp[i]])
				{
					col[tp[i]]=1;

					//对立面
					col[link[tp[i]]] = 2;

					// 子孙
					dfs(link[tp[i]]);
				}
			}

			// 所有染的点就是一组解

			FORi(2,2*N,2)
			{
				//i i+1
				//printf("颜色:[%d,%d] %d %d\n",i/2,(i+1)/2,col[id[2*i]],col[id[2*(i+1)]]);
				if(i!=2) printf(" ");
				if( col[id[2*i]]==col[id[2*0]]) printf("%d%c",i/2,(i&1)?'h':'w');
				if( col[id[2*(i+1)]]==col[id[2*0]]) printf("%d%c",(i+1)/2,((i+1)&1)?'h':'w');
			}
			printf("\n");
		}
		else
			printf("bad luck\n");
	}
	return 0;
}
posted @ 2011-03-01 16:13  AC2012  阅读(262)  评论(0编辑  收藏  举报