POJ 2942 圆桌骑士 点双连通+二分图判定
2014-01-14 19:10
393 查看
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<queue> #include<math.h> #include<stack> #include<vector> #define N 1005 #define M 1000005 using namespace std; struct Edge{ int from, to; }; int n, m; int pre , iscut , bccno , dfs_clock, bcc_cnt; vector<int> G , bcc ; stack<Edge>S; void addedge(int u, int v){ G[u].push_back(v); } int dfs(int u, int fa){ int lowu = pre[u] = ++dfs_clock; int child = 0; for(int i = 0; i < G[u].size(); i++){ int v = G[u][i]; Edge e = {u, v}; if(!pre[v]){ S.push(e); child++; int lowv = dfs(v, u); lowu = min(lowu, lowv); if(lowv >= pre[u]){ iscut[u] = true; bcc_cnt++; bcc[bcc_cnt].clear(); //连通块标号从1开始 while(1){ Edge x = S.top(); S.pop(); if(bccno[x.from] != bcc_cnt) { bcc[bcc_cnt].push_back(x.from); bccno[x.from] = bcc_cnt;} if(bccno[x.to] != bcc_cnt) { bcc[bcc_cnt].push_back(x.to); bccno[x.to] = bcc_cnt;} if(x.from == u && x.to == v)break; } } } else if(pre[v] < pre[u] && v!=fa){ S.push(e); lowu = min(lowu, pre[v]); } } if(fa < 0 && child == 1)iscut[u] = 0; return lowu; } void find_bcc(int n){ memset(pre, 0, sizeof(pre)); memset(iscut, 0, sizeof(iscut)); memset(bccno, 0, sizeof(bccno)); dfs_clock = bcc_cnt = 0; for(int i = 0; i < n; i++)if(!pre[i]) dfs(i, -1); } int map ; int odd , color ; bool bipartite(int u, int b){ for(int i = 0; i < G[u].size(); i++){ int v = G[u][i]; if(bccno[v] != b) continue; if(color[v] == color[u]) return false; if(!color[v]){ color[v] = 3 - color[u]; if(!bipartite(v, b))return false; } } return true; } void init(){ for(int i = 1; i <= n; i++)G[i].clear(), memset(map[i], 0, sizeof(map[i])); memset(odd, 0, sizeof(odd)); } int main(){ int u, v, Cas = 1; while(scanf("%d %d",&n,&m), n+m){ init(); while(m--){ scanf("%d %d", &u, &v); map[u][v] = map[v][u] = 1; } for(int i = 1; i <= n; i++) for(int j = i+1; j <= n; j++) if(!map[i][j])addedge(i, j), addedge(j, i); find_bcc(n); for(int i = 1; i <= bcc_cnt; i++) { memset(color, 0, sizeof(color)); for(int j = 0; j < bcc[i].size(); j++) bccno[bcc[i][j]] = i; int u = bcc[i][0]; color[u] = 1; if(!bipartite(u, i)) for(int j = 0; j < bcc[i].size(); j++) odd[bcc[i][j]] = 1; } int ans = n; for(int i = 1; i <= n; i++) if(odd[i]) ans--; printf("%d\n", ans); } return 0; } /* 5 5 1 4 1 5 2 5 3 4 4 5 5 11 3 1 2 4 2 1 1 1 1 3 1 1 2 1 1 3 1 1 4 3 5 8 5 8 5 3 1 2 4 2 3 5 2 1 5 2 5 2 2 4 6 8 1 4 1 5 1 6 2 4 2 5 2 6 3 6 4 5 ans: 2 0 1 3 */
相关文章推荐
- 【连通图|双连通+二分图判定】POJ-2942 Knights of the Round Table
- poj 2942 圆桌骑士 二分图判定判奇圈,点双连通分量 大白经典题目
- POJ_2942_Knights of the Round Table(点的双连通分量+二分图判定)
- poj2942 点双连通图分量+二分图判定
- poj 2942-圆桌骑士(点双连通分量+二分图)
- poj2942 Knights of the Round Table,无向图点双联通,二分图判定
- poj 2942 Knights of the Round Table(点双连通分量+二分图判定)
- POJ 2942 Knights of the Round Table(【点双连通分量】+【二分图判定】)
- poj 2942 Knights of the Round Table(无向图的双连通分量+二分图判定)
- poj2942 Knights of the Round Table,无向图点双联通,二分图判定
- poj2942圆桌骑士【点双连通分量+二分图判断】
- [POJ]2942 圆桌骑士 点双连通分量 + 二分图染色
- poj 2942 Knights of the Round Table(双连通分量+tarjan+二分图判定)
- poj 2942 Knights of the Round Table 补图+点双连通分量+判定二分图
- POJ 2942 Knights of the Round Table ★(点双连通分量+二分图判定)
- poj 2942 Knights of the Round Table(无向图的双连通分量+二分图判定)
- POJ 2942 Knights of the Round Table ★(点双连通分量+二分图判定)
- poj2942[补图+点双连通分量+交叉染色法判定二分图(奇圈判定)]
- POJ 1112 Team Them Up! 二分图判定+01背包
- POJ 2942 Knights of the Round Table 【点双联通 + 二分图染色法判奇环】