题目:n对夫妻,参加婚礼,一对夫妻不能坐在桌子的同一侧,m对有性爱关系的*男*女不能坐在桌子的同一侧,新娘新郎必须坐上桌子,输出任意一种新娘对面坐的人的情况。
这个肯定就是2-sat问题,建图时注意建新郎和新娘的边,还有缩点构造新图的时候返向建边,因为当有一条边a->b的时候,表示选a必须选b那么这样我们在选择人的时候,就会有一连串的问题,但是我们直接选b但是他可以不一定选择a,这个新图是个对称的图,因为2-sat问题建图后又很强的对称性,一个最基本的关系是题目给你的m对关系,隐含的就是夫妻关系,他们是排斥的关系,所以要标记这个关系,topsort的时候夫妻一方被选另一方自动到桌子的对面。
#include<iostream> #include<cstring> #include<cstdio> #include<stack> #include<queue> #include<vector> using namespace std; const int nodes=1000; const int edges=100000; struct node { int v,next; }e[nodes]; int n,m; int conflict[nodes],dis[nodes],in[nodes]; int head[nodes],cnt; vector<int>ve[nodes]; stack<int>s; int low[nodes],dfn[nodes],paint[nodes],instack[nodes],index,col; void Init() { while(!s.empty()) s.pop(); for(int i=0;i<=nodes;i++) ve[i].clear(); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(paint,0,sizeof(paint)); memset(instack,0,sizeof(instack)); memset(head,-1,sizeof(head)); index=col=1; cnt=0; } void add(int a,int b) { e[cnt].v=b; e[cnt].next=head[a]; head[a]=cnt++; } int MIN(int a,int b) { if(a<b) return a; return b; } void tarjan(int u) { dfn[u]=low[u]=index++; instack[u]=1; s.push(u); for(int i=head[u];i+1;i=e[i].next) { int v=e[i].v; if(!dfn[v]) { tarjan(v); low[u]=MIN(low[u],low[v]); } else if(instack[v]) { low[u]=MIN(low[u],dfn[v]); } } if(dfn[u]==low[u]) { int k=s.top(); while(k!=u) { s.pop(); paint[k]=col; instack[k]=0; k=s.top(); } s.pop(); paint[u]=col; instack[u]=0; col++; } } void Input() { for(int i=1;i<=m;i++) { int a,b; int aa,bb; char ch1,ch2; scanf("%d%c %d%c",&a,&ch1,&b,&ch2); if(ch1=='h') { a=a+n; aa=a-n; } else { aa=a+n; } if(ch2=='h') { b=b+n; bb=b-n; } else { bb=b+n; } add(a,bb); add(b,aa); } add(0,n); } void topsort() { queue<int>q; while(!q.empty()) q.pop(); for(int i=0;i<2*n;i++) { if(!in[i]) q.push(i); } while(!q.empty()) { int u=q.front(); q.pop(); if(!dis[u]) { dis[u]=1; dis[conflict[u]]=2; } for(int i=0;i<ve[u].size();i++) { int v=ve[u][i]; if(--in[v]==0) { q.push(v); } } } } void Output() { memset(conflict,0,sizeof(conflict)); memset(dis,0,sizeof(dis)); memset(in,0,sizeof(in)); for(int i=0;i<n;i++) { conflict[paint[i]]=paint[i+n]; conflict[paint[i+n]]=paint[i]; } for(int i=0;i<2*n;i++) { for(int j=head[i];j+1;j=e[j].next) { int v=e[j].v; if(paint[i]!=paint[v]) { ve[paint[v]].push_back(paint[i]); in[paint[i]]; } } } topsort(); for(int i=1;i<n;i++) { if(i!=1) printf(" "); if(dis[paint[i]]==dis[paint[0]]) { printf("%dw",i); } else printf("%dh",i); } } void treatment() { int mark=1; for(int i=0;i<2*n;i++) { if(!dfn[i]) tarjan(i); } col--; for(int i=0;i<n;i++) { if(paint[i]==paint[i+n]) { mark=0; break; } } if(!mark) printf("bad luck\n"); else Output(); } int main() { while(~scanf("%d%d",&n,&m),n+m) { Init(); Input(); treatment(); } return 0; }