一对夫妻举行婚礼,有最多30对夫妻参加,其中新娘新郎必须坐在桌子两侧。新娘看不到她所在一侧的人, 只能看到对面的人。新娘看到一对夫妻坐在一边是不吉利的。除此之外,有些人又通奸关系。看到有通奸关系的人左一边也是不吉利的。求出新娘一侧坐的人。
每个人只有两个选择,根据通奸关系建图,然后2—sat求解。
0表示新郎,1表示新娘,加一条0—>1的边,这样就可以保证选的一组解一定是新娘一边的人。
AC代码:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
const int maxn=100;
stack<int> S;
int first[maxn],rfirst[maxn],tar[maxn],sta[maxn],dfn[maxn],low[maxn],in[maxn],ret[maxn];
int size,rsize,cnt,index,n,m;
struct Edge
{
int v,next;
}edge[maxn*maxn],redge[maxn*maxn];
void insert(int u,int v)
{
edge[size].v=v;
edge[size].next=first[u];
first[u]=size++;
}
void rinsert(int u,int v)
{
redge[rsize].v=v;
redge[rsize].next=rfirst[u];
rfirst[u]=rsize++;
}
void tarjan(int u)
{
sta[u]=1; S.push(u);
dfn[u]=low[u]=++index;
for(int e=first[u];e!=-1;e=edge[e].next)
{
int v=edge[e].v;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(sta[v]) low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
int v=-1; cnt++;
while(v!=u)
{
v=S.top(); S.pop();
tar[v]=cnt; sta[v]=0;
}
}
}
void slove()
{
cnt=index=0;
memset(dfn,0,sizeof(dfn));
memset(sta,0,sizeof(sta));
for(int i=0;i<2*n;i++)
if(!dfn[i]) tarjan(i);
}
int check()
{
for(int i=0;i<n;i++)
if(tar[2*i]==tar[2*i+1])
return 0;
return 1;
}
void topsort()
{
for(int i=0;i<cnt;)
for(int j=1;j<=cnt;j++)
if(!in[j])
{
in[j]--; ret[i++]=j;
for(int e=rfirst[j];e!=-1;e=redge[e].next)
in[redge[e].v]--;
}
int flag[maxn];
memset(flag,0,sizeof(flag));
for(int i=0;i<cnt;i++)
{
for(int j=0;j<2*n;j++)
if(tar[j]==ret[i] && !flag[j^1])
flag[j]=1;
}
for(int j=2;j<2*n;j++)
if(!flag[j])
{
if(j%2) printf("%dh ",j/2);
else printf("%dw ",j/2);
}
printf("\n");
}
int main()
{
// freopen("test.txt","r",stdin);
while(scanf("%d%d",&n,&m) && n && m)
{
memset(first,-1,sizeof(first)); size=0;
memset(rfirst,-1,sizeof(rfirst)); rsize=0;
insert(0,1);
for(int i=0;i<m;i++)
{
int u,v; char cu,cv;
scanf("%d%c%d%c",&u,&cu,&v,&cv);
if(cu=='w' && cv=='w')
{ insert(2*u,2*v+1); insert(2*v,2*u+1); }
if(cu=='w' && cv=='h')
{ insert(2*u,2*v); insert(2*v+1,2*u+1); }
if(cu=='h' && cv=='w')
{ insert(2*u+1,2*v+1); insert(2*v,2*u); }
if(cu=='h' && cv=='h')
{ insert(2*u+1,2*v); insert(2*v+1,2*u); }
}
slove();
if(!check()) printf("bad luck\n");
else
{
memset(in,0,sizeof(in));
for(int u=0;u<2*n;u++)
for(int e=first[u];e!=-1;e=edge[e].next)
{
int v=edge[e].v;
if(tar[u]!=tar[v])
{
rinsert(tar[v],tar[u]);
in[tar[u]]++;
}
}
topsort();
}
}
return 0;
}