题意:
婚礼上新郎新娘坐在桌子两侧 新娘只能看见对面的人 已知一些人有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; }
原文地址:http://blog.csdn.net/houserabbit/article/details/38929833