POJ 3648 Wedding

    技术2024-08-06  55

    2-SAT问题一般指这样的问题:2n个顶点可以分为n组,每组2个顶点,且这两个顶点只能选择其中一个

     

    如果根据限制条件,选了顶点a后,必须选择b,则添加一条有向边(a,b)

     

    这题中,n对夫妻(包括新郎和新娘)恰好可以代表n组点,女的标为0,2...男的标为1,3...

     

    每对夫妻,只能选一个坐在新娘的对面,若选中一个点表示该点在新娘的对面,则对于特殊关系x,y,添加边(x,~y),(y,~x)

     

    最后添加边(0,1)

     

    代码:

    #include<iostream> #include<stack> #include<queue> using namespace std; const int MAX=100; const int inf=1<<30; struct node { int v,next; }g[MAX*MAX]; int adj[MAX],dfn[MAX],low[MAX],inStack[MAX],bel[MAX]; int ind[MAX],col[MAX],map[MAX][MAX],conflict[MAX]; int n,m,e,index,cnt; stack<int>s; void add(int u,int v) { g[e].v=v; g[e].next=adj[u]; adj[u]=e++; } void tarjan(int u) { low[u]=dfn[u]=++index; s.push(u); inStack[u]=1; int i,v; for(i=adj[u];i!=-1;i=g[i].next) { v=g[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]) { cnt++; do { v=s.top(); s.pop(); inStack[v]=0; bel[v]=cnt; }while(u!=v); } } void build_dag() { int i,u,v; for(u=0;u<2*n;u++) { for(i=adj[u];i!=-1;i=g[i].next) { v=g[i].v; if(bel[u]!=bel[v]) { map[bel[v]][bel[u]]=1; } } } for(u=1;u<=cnt;u++) { for(v=1;v<=cnt;v++) { if(map[u][v]) ind[v]++; } } } void topsort() { int i,u,v; for(i=1;i<=cnt;i++) if(ind[i]==0) { s.push(i); } while(!s.empty()) { u=s.top(); s.pop(); if(!col[u]) { col[u]=1;//每个强连通分量代表的顶点的颜色都是一样的 col[conflict[u]]=2; } for(v=1;v<=cnt;v++) { if(map[u][v]) { if(--ind[v]==0) { s.push(v); } } } } } void solve() { int i; while(!s.empty()) s.pop(); for(i=0;i<2*n;i++) if(!dfn[i]) tarjan(i); for(i=0;i<n;i++) { if(bel[2*i]==bel[2*i+1]) { puts("bad luck"); return; } conflict[bel[2*i]]=bel[2*i+1];//与它冲突的顶点所在的强连通分量 conflict[bel[2*i+1]]=bel[2*i];//原顶点冲突,所在的强连通分量也冲突 } memset(map,0,sizeof(map)); memset(ind,0,sizeof(ind)); build_dag(); memset(col,0,sizeof(col)); while(!s.empty()) s.pop(); topsort(); //cout<<col[bel[0]]<<"v"<<col[bel[1]]<<endl; for(i=2;i<2*n;i+=2) { if(i!=2) printf(" "); if(col[bel[i]]==col[bel[0]]) printf("%dw",i/2); else printf("%dh",i/2); } printf("/n"); } int main() { int i,j,ii,jj; char c1,c2; while(scanf("%d%d",&n,&m)!=EOF) { if(n==0&&m==0) break; memset(adj,-1,sizeof(adj)); memset(dfn,0,sizeof(dfn)); memset(inStack,0,sizeof(inStack)); e=cnt=index=0; while(m--) { scanf("%d%c %d%c",&i,&c1,&j,&c2); if(c1=='h') { i=2*i+1;//男 ii=i-1;//女 } else { i=2*i;//女 ii=i+1;//男 } if(c2=='h') { j=2*j+1; jj=j-1; } else { j=2*j; jj=j+1; } add(i,jj); //cout<<i<<" "<<jj<<endl; add(j,ii); //cout<<j<<" "<<ii<<endl; } add(0,1); solve(); } return 0; } 

    最新回复(0)