题目分析:比较赤果果的一道2-sat。
对于编号为i的夫妻,i<<1为妻子,i<<1|1为丈夫。
如果有两个人x,y有奸情,则建边:< x , y ^ 1 > , < y , x ^ 1 >
因为新郎必须坐在新娘的对面,所以建边< 0 , 1 >
最后强连通加逆拓扑排序后,颜色为1的是坐在新郎那一边的(因为那边的所有人都不会有奸情)。
颜色为2的就是坐在新娘这边的(不晦气仅仅指新娘对面不能有通奸的,对于新娘这边没有要求)
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define REP( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i )
#define FOR( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )
#define REV( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
#define CLR( a , x ) memset ( a , x , sizeof a )
#define CPY( a , x ) memcpy ( a , x , sizeof a )
const int MAXN = 60 ;
const int MAXE = 10000 ;
struct Edge {
int v ;
Edge* next ;
} E[MAXE] , *H[MAXN] , *cur , t_E[MAXE] , *t_H[MAXN] , *t_cur ;
int dfn[MAXN] , low[MAXN] , scc[MAXN] , scc_cnt ;
int S[MAXN] , top , dfs_clock ;
int n , m ;
int in[MAXN] ;
int Q[MAXN] , head , tail ;
int color[MAXN] ;
int opp[MAXN] ;
void init () {
cur = E ;
top = scc_cnt = dfs_clock = 0 ;
CLR ( H , 0 ) ;
CLR ( dfn , 0 ) ;
CLR ( scc , 0 ) ;
}
void t_init () {
t_cur = t_E ;
CLR ( t_H , 0 ) ;
CLR ( in , 0 ) ;
}
void addedge ( int u , int v ) {
cur -> v = v ;
cur -> next = H[u] ;
H[u] = cur ++ ;
}
void t_addedge ( int u , int v ) {
t_cur -> v = v ;
t_cur -> next = t_H[u] ;
t_H[u] = t_cur ++ ;
}
void tarjan ( int u ) {
dfn[u] = low[u] = ++ dfs_clock ;
S[top ++] = u ;
for ( Edge* e = H[u] ; e ; e = e -> next ) {
int v = e -> v ;
if ( !dfn[v] ) {
tarjan ( v ) ;
low[u] = min ( low[u] , low[v] ) ;
} else if ( !scc[v] ) low[u] = min ( low[u] , dfn[v] ) ;
}
if ( low[u] == dfn[u] ) {
++ scc_cnt ;
do {
scc[S[-- top]] = scc_cnt ;
} while ( u != S[top] ) ;
}
}
int ok () {
REP ( i , 0 , n << 1 ) if ( !dfn[i] ) tarjan ( i ) ;
REP ( i , 0 , n ) if ( scc[i << 1] == scc[i << 1 | 1] ) return 0 ;
REP ( i , 0 , n ) {
opp[scc[i << 1]] = scc[i << 1 | 1] ;
opp[scc[i << 1 | 1]] = scc[i << 1] ;
}
return 1 ;
}
void topo () {
head = tail = 0 ;
CLR ( color , 0 ) ;
FOR ( i , 1 , scc_cnt ) if ( !in[i] ) Q[tail ++] = i ;
while ( head != tail ) {
int u = Q[head ++] ;
if ( !color[u] ) {
color[u] = 1 ;
color[opp[u]] = 2 ;
for ( Edge* e = t_H[u] ; e ; e = e -> next )
if ( -- in[e -> v] == 0 )
Q[tail ++] = e -> v ;
}
}
}
void solve () {
int u , v , ui , vi ;
char c1 , c2 ;
init () ;
addedge ( 0 , 1 ) ;
while ( m -- ) {
scanf ( "%d%c%d%c" , &u , &c1 , &v , &c2 ) ;
ui = c1 == 'w' ? 0 : 1 ;
vi = c2 == 'w' ? 0 : 1 ;
addedge ( ( u << 1 ) ^ ui , ( v << 1 | 1 ) ^ vi ) ;
addedge ( ( v << 1 ) ^ vi , ( u << 1 | 1 ) ^ ui ) ;
}
if ( ok () ) {
t_init () ;
REP ( i , 0 , n << 1 )
for ( Edge* e = H[i] ; e ; e = e -> next )
if ( scc[e -> v] != scc[i] ) {
t_addedge ( scc[e -> v] , scc[i] ) ;
++ in[scc[i]] ;
}
topo () ;
REP ( i , 1 , n )
printf ( "%d%c%c" , i , color[scc[i << 1]] == 2 ? 'w' : 'h' , i < n - 1 ? ' ' : '\n' ) ;
} else printf ( "bad luck\n" ) ;
}
int main () {
while ( ~scanf ( "%d%d" , &n , &m ) && ( n || m ) ) solve () ;
return 0 ;
}