POJ 3648 Wedding(2-SAT)
2016-09-17 22:41
411 查看
【题意】:有一对新人结婚,邀请n对夫妇去参加婚礼。
有一张很长的桌子,人只能坐在桌子的两边,还要满
足下面的要求:1.每对夫妇不能坐在同一侧 2.n对夫妇
之中可能有通奸关系(包括男男,男女,女女),有通
奸关系的不能同时坐在新娘的对面,可以分开坐,可以
同时坐在新娘这一侧。如果存在一种可行的方案,输出
与新娘同侧的人。
输出任意一组解,点的编号从0~2n-1
取和新郎同一侧的,输出的时候反一下就变成和新娘同一侧的了
有一张很长的桌子,人只能坐在桌子的两边,还要满
足下面的要求:1.每对夫妇不能坐在同一侧 2.n对夫妇
之中可能有通奸关系(包括男男,男女,女女),有通
奸关系的不能同时坐在新娘的对面,可以分开坐,可以
同时坐在新娘这一侧。如果存在一种可行的方案,输出
与新娘同侧的人。
输出任意一组解,点的编号从0~2n-1
取和新郎同一侧的,输出的时候反一下就变成和新娘同一侧的了
#include<stdio.h> #include<iostream> #include<algorithm> #include<vector> #include<queue> #include<string.h> using namespace std; const int MAXN=200;// char color[MAXN];//染色 bool visit[MAXN]; queue<int>q1,q2; //vector建图方法很妙 vector<vector<int> >adj; //原图 //中间一定要加空格把两个'>'隔开 vector<vector<int> >radj;//逆图 vector<vector<int> >dag;//缩点后的逆向DAG图 int n,m,cnt; int id[MAXN],order[MAXN],ind[MAXN];//强连通分量,访问顺序,入度 void dfs(int u) { visit[u]=true; int i,len=adj[u].size(); for(i=0;i<len;i++) if(!visit[adj[u][i]]) dfs(adj[u][i]); order[cnt++]=u; } void rdfs(int u) { visit[u]=true; id[u]=cnt; int i,len=radj[u].size(); for(i=0;i<len;i++) if(!visit[radj[u][i]]) rdfs(radj[u][i]); } void korasaju() { int i; memset(visit,false,sizeof(visit)); for(cnt=0,i=0;i<2*n;i++) if(!visit[i]) dfs(i); memset(id,0,sizeof(id)); memset(visit,false,sizeof(visit)); for(cnt=0,i=2*n-1;i>=0;i--) if(!visit[order[i]]) { cnt++;//这个一定要放前面来 rdfs(order[i]); } } bool solvable() { for(int i=0;i<n;i++) if(id[2*i]==id[2*i+1]) return false; return true; } void topsort() { int i,j,len,now,p,pid; while(!q1.empty()) { now=q1.front(); q1.pop(); if(color[now]!=0)continue; color[now]='R'; ind[now]=-1; for(i=0;i<2*n;i++) { if(id[i]==now) { //p=(i%2)?i+1:i-1;//点的编号从0开始以后这一定要修改 p=i^1; pid=id[p]; q2.push(pid); while(!q2.empty()) { pid=q2.front(); q2.pop(); if(color[pid]=='B')continue; color[pid]='B'; len=dag[pid].size(); for(j=0;j<len;j++) q2.push(dag[pid][j]); } } } len=dag[now].size(); for(i=0;i<len;i++) { ind[dag[now][i]]--; if(ind[dag[now][i]]==0) q1.push(dag[now][i]); } } } int main() { int x,y; char c1,c2; int i,j; int len; while(scanf("%d%d",&n,&m)!=EOF) { if(n==0&&m==0)break; adj.assign(2*n,vector<int>()); radj.assign(2*n,vector<int>()); while(m--) { scanf("%d%c%d%c",&x,&c1,&y,&c2); if(c1=='w')x=2*x; else x=2*x+1; if(c2=='w')y=2*y; else y=2*y+1; if(x!=(y^1)) { adj[x].push_back(y^1); adj[y].push_back(x^1); radj[y^1].push_back(x); radj[x^1].push_back(y); } } adj[0].push_back(1); radj[1].push_back(0); //加一条新娘到新郎的边。 //表示选了新娘必选新郎,这样如果选了新娘就会判断无解。 //这样选出来的组合必定是有新郎的,即和新郎坐在同一侧的 korasaju(); if(!solvable())printf("bad luck\n"); else { dag.assign(cnt+1,vector<int>()); memset(ind,0,sizeof(ind)); memset(color,0,sizeof(color)); for(i=0;i<2*n;i++) { len=adj[i].size(); for(j=0;j<len;j++) if(id[i]!=id[adj[i][j]]) { dag[id[adj[i][j]]].push_back(id[i]); ind[id[i]]++; } } for(i=1;i<=cnt;i++) if(ind[i]==0) q1.push(i); topsort(); for(i=1;i<n;i++)//小心别写错,是color[id[ { if(i>1)printf(" "); if(color[id[2*i]]=='R')printf("%dh",i);//选取的是和新郎同一侧的,输出和新娘同一侧的 //所以输出的时候h和w换一下 else printf("%dw",i); } printf("\n"); } } return 0; }
相关文章推荐
- |poj 3648|2-SAT|Wedding
- 2-sat->poj 3648 Wedding
- POJ 3648 - Wedding...阅读理解.题意坑爹.2-sat..细节注意
- POJ-3648 Wedding 2sat
- Wedding (poj 3648 2-SAT 输出任意一组解)
- POJ 3648 Wedding(2-SAT 拓扑排序输出任意一种解决方案)
- poj 3648 Wedding 2-SAT
- poj 3648 wedding(2-sat 拓扑排序输出方案)
- poj 3648 Wedding(2-sat)
- poj 3648 Wedding 2-SAT
- POJ 3648 Wedding 2-SAT
- POJ 3648 Wedding(2-SAT)
- POJ_3648 Wedding 2-Sat
- POJ 3648-Wedding(2-SAT)
- 【POJ】3648 Wedding 2-sat
- POJ-3648-Wedding(2-sat)
- poj 3648 Wedding 2_SAT
- poj 3648 Wedding(2-sat 求解)
- [2-sat][topsort输出解] POJ 3648 Wedding
- [2-sat][topsort输出解] POJ 3648 Wedding