题意:
婚礼上新郎新娘坐在桌子两侧 新娘只能看见对面的人 已知一些人有XX关系… 新娘不想看见有关系的同时坐在对面 问 满足条件的情况下 新娘这边做的人是谁
思路:
新郎那一边的约束最多 有利于解题 那么就变成了 一个人要不要坐新郎这边的2-sat问题 因此可以先求新郎这边的人 然后反一下就是新娘这边的了 注意 新郎是必选点 而且 不能选和新郎有XX关系的…
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 70
int n,m,tot,top,idx,cnt;
int dfn[N],low[N],st[N],instack[N],belong[N],col[N],in[N],head[N],opt[N],qu[N];
struct edge
{
int u,v,next;
}ed[N*N*2];
void add(int u,int v)
{
ed[tot].u=u;
ed[tot].v=v;
ed[tot].next=head[u];
head[u]=tot++;
}
void tarjan(int u)
{
int i,v;
dfn[u]=low[u]=++idx;
instack[u]=1;
st[++top]=u;
for(i=head[u];~i;i=ed[i].next)
{
v=ed[i].v;
if(dfn[v]==-1)
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(instack[v]&&dfn[v]<low[u]) low[u]=dfn[v];
}
if(dfn[u]==low[u])
{
cnt++;
do
{
v=st[top--];
instack[v]=0;
belong[v]=cnt;
}while(u!=v);
}
}
bool can()
{
int i,j;
top=idx=cnt=0;
for(i=0;i<n;i++) dfn[i]=-1;
for(i=0;i<n;i++)
{
if(dfn[i]==-1) tarjan(i);
}
for(i=0;i<n;i+=2)
{
if(belong[i]==belong[i^1]) return false;
}
return true;
}
void solve()
{
int i,u,v,s=tot,l,r;
for(i=1;i<=cnt;i++)
{
head[i]=-1;
in[i]=0;
col[i]=0;
}
tot=0;
for(i=0;i<s;i++)
{
u=belong[ed[i].u];
v=belong[ed[i].v];
if(u!=v)
{
add(v,u);
in[u]++;
}
}
for(i=0;i<n;i++) opt[belong[i]]=belong[i^1];
l=r=0;
for(i=1;i<=cnt;i++)
{
if(!in[i]) qu[r++]=i;
}
while(l<r)
{
u=qu[l++];
if(!col[u])
{
col[u]=1;
col[opt[u]]=2;
}
for(i=head[u];~i;i=ed[i].next)
{
v=ed[i].v;
in[v]--;
if(!in[v]) qu[r++]=v;
}
}
}
int main()
{
int i,j;
char hw;
while(~scanf("%d%d",&n,&m))
{
if(!n&&!m) break;
n<<=1;
tot=0;
for(i=0;i<n;i++) head[i]=-1;
while(m--)
{
scanf("%d%c",&i,&hw);
i<<=1;
if(hw=='h') i^=1;
scanf("%d%c",&j,&hw);
j<<=1;
if(hw=='h') j^=1;
add(j^1,i);
add(i^1,j);
}
add(1,0);
if(can())
{
solve();
for(i=2;i<n;i+=2)
{
printf("%d",i/2);
if(col[belong[i]]==1) putchar('w');
else putchar('h');
if(i!=n-2) putchar(' ');
else putchar('\n');
}
}
else puts("bad luck");
}
return 0;
}