poj 3648 2-SAT建图+topsort输出结果

来源:互联网 发布:最好用的编程软件 编辑:程序博客网 时间:2024/06/07 03:32

其实2-SAT类型题目的类型比较明确,基本模型差不多是对于n组对称的点,通过给出的限制条件建图连边,然后通过缩点和判断冲突来解决问题。要注意的是在topsort输出结果的时候,缩点后建图需要反向连边,然后输出就可以了。2-sat题型差不多。

 

题意:新娘新郎分别坐在长桌两边,n-1队夫妇来参加婚礼,要求:夫妇不能坐在同一边,通奸关系不能坐在同一边。输出新娘对面的序列。

 

思路:对称关系:夫妇,限制条件:通奸关系。基础2-sat问题,缩点找冲突topsort输出结果一气呵成。。。

 

代码:

#include<iostream>#include<cstdio>#include<cstring>using namespace std;#define MAXN 2002int instack[MAXN],stack[MAXN],fa[MAXN],vis[MAXN],head[MAXN],first[MAXN];int dfn[MAXN],low[MAXN],in[MAXN],ans[MAXN],que[MAXN];int a[MAXN][2],b[MAXN][2],flag[MAXN],cf[MAXN],col[MAXN];int n,m,tot,scnt,time,tt,top,index;struct Edge{int v,next;}edge[MAXN*MAXN],e[MAXN*MAXN];void addedge(int u,int v){edge[tot].v=v;edge[tot].next=head[u];head[u]=tot++;}void adde(int u,int v){e[tt].v=v;e[tt].next=first[u];first[u]=tt++;}void tarjan(int u){instack[u]=1;stack[top++]=u;dfn[u]=low[u]=++index;int v;for(int i=head[u];i!=-1;i=edge[i].next){v=edge[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(low[u]==dfn[u]){scnt++;do{v=stack[--top];instack[v]=0;fa[v]=scnt;}while(v!=u);}}void build(){for(int i=0;i<m;i++)          //2*n的点{int t1,t2;char c,v;scanf("%d%c",&t1,&c);scanf("%d%c",&t2,&v);if(c=='h'&&v=='h'){addedge(t1+n,t2);addedge(t2+n,t1);}else if(c=='h'&&v=='w'){addedge(t1+n,t2+n);addedge(t2,t1);}else if(c=='w'&&v=='h'){addedge(t1,t2);addedge(t2+n,t1+n);}else if(c=='w'&&v=='w'){addedge(t1,t2+n);addedge(t2,t1+n);}}addedge(0,n);}void solve(){memset(dfn,0,sizeof(dfn));memset(instack,0,sizeof(instack));index=0;scnt=0;top=0;for(int i=0;i<2*n;i++){if(!dfn[i])tarjan(i);}}int check(){for(int i=0;i<n;i++){if(fa[i]==fa[i+n])   //冲突{return 0;}cf[fa[i]]=fa[i+n];cf[fa[i+n]]=fa[i];}return 1;}void topsort(){int head=1,tail=1;for(int i=1;i<=scnt;i++){if(in[i]==0){que[tail++]=i;}}int v;while(tail>head){int u=que[head];head++;if(col[u]==0)     //对于未着色的点x,将x染成红色1,同时将与x矛盾的点cf[x]染成蓝色-1。{col[u]=1;col[cf[u]]=-1;}for(int i=first[u];i!=-1;i=e[i].next){v=e[i].v;if(--in[v]==0){que[tail++]=v;}}}memset(ans,0,sizeof(ans));for(int i=0;i<n;i++){if(col[fa[i]]==1){ans[i]=1;}}for(int i=1;i<n;i++){if(ans[i])printf("%dh ",i);elseprintf("%dw ",i);}printf("\n");}int main(){while(scanf("%d%d",&n,&m)!=EOF,(n||m)){memset(head,-1,sizeof(head));tot=0;memset(first,-1,sizeof(first));tt=0;build();solve();if(!check())printf("bad luck\n");else{memset(in,0,sizeof(in));memset(col,0,sizeof(col));for(int i=0;i<2*n;i++){int v;for(int j=head[i];j!=-1;j=edge[j].next){v=edge[j].v;if(fa[i]!=fa[v]){adde(fa[v],fa[i]);in[fa[i]]++;}}}topsort();}}return 0;}


 

原创粉丝点击