题意:
新郎新娘宴会,宴会上一共有 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