POJ 3648 Wedding (Tarjan + 缩点 + 拓扑排序)
来源:互联网 发布:淘宝代办签证靠谱吗 编辑:程序博客网 时间:2024/05/18 19:22
题目链接:
http://poj.org/problem?id=3648
题解:
2-SAT问题,不过我用Tarjan + 缩点 + 拓扑排序做的。。。这样可以输出一组可行解,但是我不知道怎么输出字典树最小的解。。比较尴尬。
AC代码:
#include <iostream>#include <cstdio>#include <algorithm>#include <vector>#include <cstring>#include <stack>#include <queue>using namespace std;vector <int> mapp[10000];vector <int> remap[10000];int dfn[10000],low[10000],stk[10000],vis[10000],color[10000],conflict[10000],col[10000],degree[10000];int cnt,t,sig;int n,m,a,b,x1,y1,x2,y2;char c,d;void init(){ memset(vis,0,sizeof(vis)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(color,0,sizeof(color)); memset(stk, 0, sizeof(stk)); memset(conflict, 0, sizeof(conflict)); memset(col, 0, sizeof(col)); memset(degree, 0, sizeof(degree)); for(int i=1;i<=2*n;i++) { mapp[i].clear(); remap[i].clear(); }}void Tarjan(int u){ vis[u] = 1; low[u] = dfn[u] = cnt++; stk[++t] = u; for(int i = 0; i < mapp[u].size(); i++) { int v = mapp[u][i]; if(!vis[v]) Tarjan(v); if(vis[v] == 1) low[u] = min(low[u],low[v]); } if(dfn[u] == low[u]) { sig++; do { color[stk[t]] = sig; vis[stk[t]] = -1; } while(stk[t--] != u); }}void rebuild()//反向构图{ for(int i=1;i <= 2*n;i++) { for(int j=0;j< mapp[i].size();j++) { int v = mapp[i][j]; if(color[i] != color[v]) { degree[color[i]]++; remap[color[v]].push_back(color[i]); } } }}void topsort(){ queue<int> qq; for(int i = 1 ;i <= sig;i++) {//现在对缩点后的图进行拓扑 if(!degree[i]) { qq.push(i); } } while(!qq.empty()) { int u = qq.front(); qq.pop(); if(!col[u]) { col[u] = 1;//红色 col[conflict[u]] = 2;//蓝色(因为缩点后变成有向无环图,对应的冲突点只有确定的一个) } for(int i=0;i<remap[u].size();i++) { int vv = remap[u][i]; degree[vv]--; if(!degree[vv])qq.push(vv); } }}int main(){ while(~scanf("%d %d", &n, &m) && (n+m)) { init(); for(int i = 1; i <= m; i++) { int x,y; scanf("%d%c %d%c", &x, &c, &y, &d); if(c == 'h') { x1 = 2*x+2;//man y1 = 2*x+1;//woman } else { x1 = 2*x+1;//woman y1 = 2*x+2;//man } if(d == 'h') { x2 = 2*y+2;//man y2 = 2*y+1;//woman } else { x2 = 2*y+1;//woman y2 = 2*y+2;//man } mapp[x1].push_back(y2); mapp[x2].push_back(y1); } mapp[1].push_back(2); cnt = 1, t = -1, sig = 0; for(int i = 1; i <= 2 * n; i++) { if(!vis[i]) Tarjan(i); } // for(int i = 1; i <= 2 * n; i++) // cout << i << " " <<color[i] <<endl; bool flag=true; for(int i = 0; i < n; i++ ) { if(color[2*i + 1]==color[2*i + 2]) { flag=false; break; } } if(flag) { for(int i = 1 ; i <= 2*n;i+=2) { int aa = color[i],bb = color[i+1]; conflict[aa] = bb; conflict[bb] = aa; } rebuild(); topsort(); //for(int i = 0; i <= 2*n; i++) // cout << col[i] <<endl; for(int i=3; i<= 2*n; i+=2) { if(i!=3) printf(" "); if(col[color[i]] == col[color[1]]) printf("%dw",i/2); else printf("%dh",i/2);//否则,取她的老公 } puts(""); } else puts("bad luck"); }}
0 0
- POJ 3648 Wedding (Tarjan + 缩点 + 拓扑排序)
- Poj 3648 Wedding【2-Sat--------Tarjan强连通+缩点染色+拓扑排序】
- poj 3648 Wedding+2-sat+SCC+缩点+拓扑排序
- poj 3648 Wedding 【2-sat 经典建图 输出一组可行解 好题】 【tarjan求SCC + 缩点 + 拓扑排序 + 染色】
- poj 2762 tarjan+缩点+拓扑排序
- poj 3160【tarjan缩点+拓扑排序+DP】
- poj 3648 Wedding(2-sat--拓扑排序输出可行解)
- poj 3648 wedding(2-sat 拓扑排序输出方案)
- POJ 3648 Wedding(2-SAT 拓扑排序输出任意一种解决方案)
- 2-SAT ( Tarjan )——Wedding (POJ 3648)
- vector表示十字链表+Tarjan+缩点+拓扑排序 详解 poj 2762
- UOJGraph(tarjan缩点+拓扑)
- hdu 6165 FFF at Valentine(tarjan缩点+拓扑排序)
- POJ--2762--Going from u to v or from v to u?【tarjan缩点+拓扑排序】
- BZOJ 1093 最大半连通子图(tarjan缩点 拓扑排序)
- HDU6165 FFF at Valentine(并查集+tarjan缩点+拓扑排序)
- HDU 6165 FFF at Valentine(tarjan缩点+拓扑排序)
- bzoj2208 [Jsoi2010]连通数(tarjan缩点+拓扑排序+bitset传递闭包)
- Iterator iterator():迭代器,集合的专用遍历方式
- Centos 7 刚安装不能上网的问题
- 有一个二维数组.----杨氏矩阵
- 在Win7中好像无法成功申请证书的解决办法。已验证
- HDU 3461 Code Lock
- POJ 3648 Wedding (Tarjan + 缩点 + 拓扑排序)
- Linux(树梅派) 主机名、密码配置
- poj 2983 差分路径+SPFA
- 171.leetcode Excel Sheet Column Number(easy)[进制转换]
- 学习资料
- Python学习笔记二:IDE环境搭建
- 存储自定义对象并遍历Student(name,age)
- Android实现多张图片合成GIF
- (NYoj 214)单调递增子序列(二) --非递归思想模板