天天看點

poj 3648 Wedding

題意:

新郎新娘宴會,宴會上一共有 n 對夫婦,編号分别為 0 ~ n - 1,其中新郎新娘編号為 0,丈夫為 h,妻子為 w 。

宴會的長桌上,新郎新娘各坐一邊,兩邊人數各為 n。在所有人中,存在 m 對異常關系,現在要求,新娘對面的那一邊所有人之間不能存在異常關系,要求你求出新娘的這邊的坐的人。這裡的異常關系指偷情(男男、男女、女女)。

分析:

沖突關系,有異常關系的兩人不能同時存在,即 a && b == 0。(a 與 b 兩個可以選擇其中一人做新郎這一邊,也可以選擇都坐在新娘這一邊)

需要注意的是,新郎必須在,是以必須在圖中加一條 0 -> n 的邊。(證明請找度娘,謝謝)

此外,有一點很要命,輸入不要"%s%s",測試資料中存在無空格輸入的現象,用“%d%c %d%c”吧,這個,我表示我畫了一個小時陷在這個坑裡,悲催呀。。。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 11000;
const int inf = 1000000000;
vector<int>edge[maxn];
int n, m;
int tmpdfn, dfn[maxn], low[maxn], inst[maxn], belong[maxn], st[maxn], top, scnt;
int opp[maxn], in[maxn], color[maxn];
vector<int>arc[maxn];
queue<int>q;
void tarjan( int u )
{
	int i, v, t, size;
	low[u] = dfn[u] = tmpdfn++;
	st[top++] = u;
	inst[u] = 1;
	size = edge[u].size();
	for( i = 0; i < size; i++ )
	{
		v = edge[u][i];
		if( dfn[v] == -1 )
		{
			tarjan( v );
			low[u] = min( low[u], low[v] );
		}
		else if( inst[v] )low[u] = min( low[u], dfn[v] );
	}
	if( dfn[u] == low[u] )
	{
		do{ belong[t = st[--top]] = scnt; inst[t] = 0; }while( t != u );
		scnt++;
	}
}
bool SCC()
{
	int i;
	top = 0;
	tmpdfn = scnt = 1;
	memset( dfn, -1, sizeof(dfn) );
	memset( inst, 0, sizeof(inst) );
	for( i = 1; i <= n * 2; i++ )if( dfn[i] == -1 )tarjan( i );
	for( i = 1; i <= n; i++ )if( belong[i] == belong[i + n] )return false;
	return true;
}
void rebuild()
{
	memset( in, 0, sizeof(in) );
	int u, v, i, size;
	for( i = 1; i <= n * 2; i++ )arc[i].clear();
	for( u = 1; u <= n * 2; u++ )
	{
		size = edge[u].size();
		for( i = 0; i < size; i++ )
		{
			v = edge[u][i];
			if( belong[u] != belong[v] )
			{
				arc[belong[v]].push_back( belong[u] );
				in[belong[u]]++;
			}
		}
	}
}
void topusort()
{
	int i, j, u, v, size;
	while( !q.empty() )q.pop();
	memset( color, 0, sizeof(color) );
	for( i = 1; i < scnt; i++ )if( !in[i] )
		q.push( i );
	while( !q.empty() )
	{
		u = q.front();	q.pop();
		if( !color[u] )color[u] = 1, color[opp[u]] = 2;
		size = arc[u].size();
		for( i = 0; i < size; i++ )
		{	
			v = arc[u][i];
			in[v]--;
			if( !in[v] )q.push( v );
		}
	}
}
int main()
{
	int i, j, a, b, aa, bb;
	char s1, s2;
	while( ~scanf( "%d%d", &n, &m ), n + m )
	{
		for( i = 1; i <= n * 2; i++ )edge[i].clear();
		while( m-- )
		{
			scanf( "%d%c %d%c", &a, &s1, &b, &s2 );	// %s%s 輸入有誤,案例中輸入無空格
			a++;	b++;
			aa = s1 == 'w' ? 0 : 1;
			bb = s2 == 'w' ? 0 : 1;
			edge[a + aa * n].push_back( b + (!bb) * n );
			edge[b + bb * n].push_back( a + (!aa) * n );
		}
		edge[1].push_back( 1 + n );
		if( SCC() )
		{
			for( i = 1; i <= n; i++ )
			{
				opp[belong[i]] = belong[i + n];
				opp[belong[i + n]] = belong[i];
			}
			rebuild();
			topusort();
			for( i = 2; i <= n; i++ )
				if( color[belong[i]] == color[belong[1]] )printf( "%dw ", i - 1 );
				else printf( "%dh ", i - 1 );
			puts("");
		}
		else
			puts( "bad luck" );
	}
	return 0;
}
//1h 2w 3w 4h 5w 6w 7h 8w 9h