// 题目来源:POJ 3648 // 题目大意:有n对夫妻参加婚礼,现安排座位,已经某些人不能同时坐在新娘的对面,且夫妻不可同侧,求可行方案 // 解决方法:仍然2-sat建图解决 // 特别注意:新娘到新郎要连边,因为选出的必须是新郎 #include <cstdio> #include <string> #define o 100000 #define _ 1000000 using namespace std; void link( int, int ); void link2( int, int ); void tarjan( int ); void topsort( int ); void dfs( int ); int next[_], next2[_], g[_], g2[_]; int h[o], h2[o], dfn[o], low[o], stack[o], done[o], code[o], color[o], cfl[o], id[o]; int n, m, top, t, t2, tt, index, cnt; bool ins[o]; bool ok; int main( ) { freopen( "3648.in", "r", stdin ); freopen( "3648.out", "w", stdout ); scanf( "%d%d", &n, &m ); int aa, bb; char ch, ch2; while( n != 0 ) { memset( next, 0, sizeof( next ) ); memset( next2, 0, sizeof( next2 ) ); memset( h, 0, sizeof( h ) ); memset( h2, 0, sizeof( h2 ) ); memset( dfn, 0, sizeof( dfn ) ); memset( low, 0, sizeof( low ) ); memset( code, 0, sizeof( code ) ); memset( color, 0, sizeof( color ) ); memset( id, 0, sizeof( id ) ); memset( cfl, 0, sizeof( cfl ) ); t = t2 = tt = index = cnt = 0; ok = true; while( m-- ) { scanf( "%d%c%d%c", &aa, &ch, &bb, &ch2 ); aa *= 2; if( ch == 'w' ) aa ^= 1; bb *= 2; if( ch2 == 'w' ) bb ^= 1; link( aa, bb^1 ); link( bb, aa^1 ); } link( 1, 0 ); for( int i = 0; i < 2*n; i++ ) if( !dfn[i] ) tarjan( i ); for( int i = 0; i < 2*n; i++ ) if( code[i] == code[i^1] ) { printf( "bad luck\n" ); ok = false; break; } if( ok ) { for( int i = 0; i < 2*n; i++ ) { for( int k = h[i]; k; k = next[k] ) { int j = g[k]; if( code[i] == code[j] ) continue; link2( code[j], code[i] ); id[ code[i] ]++; } cfl[ code[i] ] = code[i^1]; cfl[ code[i^1] ] = code[i]; } for( int i = 1; i <= cnt; i++ ) if( id[i] == 0 ) topsort( i ); for( int ii = 1; ii <= cnt; ii++ ) { int i = done[ii]; if( color[i] != 0 ) continue; color[i] = 1; dfs( cfl[i] ); } for( int i = 2; i < 2*n; i++ ) if( color[ code[i] ] == 2 ) if( ( i & 1 ) == 0 ) printf( "%dh ", i/2 ); else printf( "%dw ", i/2 ); printf( "\n" ); } scanf( "%d%d", &n, &m ); } } void link( int aa, int bb ) { next[++t] = h[aa]; h[aa] = t; g[t] = bb; } void link2( int aa, int bb ) { next2[++t2] = h2[aa]; h2[aa] = t2; g2[t2] = bb; } void tarjan( int i ) { int j; dfn[i] = low[i] = ++index; stack[++top] = i; ins[i] = true; for( int k = h[i]; k; k = next[k] ) { j = g[k]; if( !dfn[j] ) { tarjan( j ); if( low[j] < low[i] ) low[i] = low[j]; } else if( ins[j] && dfn[j] < low[i] ) low[i] = dfn[j]; } if( dfn[i] == low[i] ) { cnt++; do { j = stack[top--]; ins[j] = false; code[j] = cnt; } while( i != j ); } } void topsort( int i ) { int j; id[i] = -1; done[++tt] = i; for( int k = h2[i]; k; k = next2[k] ) { j = g2[k]; id[j]--; if( id[j] == 0 ) topsort( j ); } } void dfs( int i ) { int j; color[i] = 2; for( int k = h2[i]; k; k = next2[k] ) { j = g2[k]; if( color[j] == 0 ) dfs( j ); } }