题意不多说,其实是不想说=。=...
解法:2-SAT问题,设第i对夫妇中,2*i为妻子,2*i+1为丈夫。
若两人有不正常关系,如a和b,则需要添加边a->!b , b->!a (!a和!b表示不选他(她),选其配偶)。
另外还要再加一条0->1的边表示选择新郎。
然后求强连通分量看是否会有bad lucky,若没有bad lucky,则对图进行染色即可。与新娘同色的即为与新娘坐在同一边的。
//time:0ms
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
int n,m,cnt,num;
vector<int> G[5010];
int color[5010];
int pre[5010],scc[5010],low[5010];
int f[5010];
stack<int> s;
queue<int> q;
void init()
{
while(!s.empty()) s.pop();
cnt=0,num=0;
memset(color,0,sizeof color);
for(int i=0;i<(n<<1);++i)
G[i].clear();
memset(pre,0,sizeof pre);
memset(color,0,sizeof color);
memset(scc,0,sizeof scc);
}
void DFS(int u)
{
pre[u]=low[u]=++num;
s.push(u);
for(int i=0;i<G[u].size();++i) {
int v=G[u][i];
if(!pre[v]) {
DFS(v);
low[u]=min(low[u],low[v]);
}
else if(!scc[v]) low[u]=min(low[u],pre[v]);
}
if(pre[u]==low[u]) {
int tmp=-1;
++cnt;
while(tmp!=u) {
tmp=s.top();
s.pop();
scc[tmp]=cnt;
}
}
}
void tocolor()
{
for(int i=1;i<=cnt;++i) {
if(!color[i]) {
color[i]=1;
color[f[i]]=2;
}
}
}
void solve()
{
for(int i=0;i<(n<<1);++i)
if(!pre[i]) DFS(i);
for(int i=0;i<n;++i)
if(scc[i<<1]==scc[i<<1|1]){
printf("bad luck\n");
return;
}
else {
f[scc[i<<1]]=scc[i<<1|1];
f[scc[i<<1|1]]=scc[i<<1];
}
tocolor();
int flag=0;
for(int i=2;i<(n<<1);i+=2) {
if(flag) printf(" ");
if(color[scc[i]]==color[scc[0]]) printf("%dw",i>>1);
else printf("%dh",i>>1);
flag=1;
}
printf("\n");
}
int main()
{
char ch1,ch2;
int x,y;
int a,b,c,d;
while(scanf("%d%d",&n,&m)&&(n|m)) {
init();
while(m--) {
scanf("%d%c %d%c",&x,&ch1,&y,&ch2);
a=2*x,b=a+1;
c=2*y,d=c+1;
if(ch1=='h') {
if(ch2=='h') {
G[b].push_back(c);
G[d].push_back(a);
}
else {
G[b].push_back(d);
G[c].push_back(a);
}
}
else {
if(ch2=='h') {
G[a].push_back(c);
G[d].push_back(b);
}
else {
G[a].push_back(d);
G[c].push_back(b);
}
}
}
G[0].push_back(1);
solve();
}
}