POJ 3648 Wedding 2-sat输出一组解

来源:互联网 发布:天狮多种vb片功效 编辑:程序博客网 时间:2024/05/21 17:19

题目: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;} 

0 0
原创粉丝点击