Knights of the Round Table
2014-03-28 10:52
211 查看
题目链接
题意:
n个人开会,会议人数至少为三且为奇数。有些人相互憎恨,这些人不能邻座。统计有几个人不能参加任意一个会议
输入:n,m。m行包括两个整数k1、k2表示两个人相互憎恨。输入结束标志为n=m=0
输出:无法参加任何会议的人数
分析:
对于存在割点的图,割点两侧的人肯定不能在一个会议中(不能构成环)。而对于不存在割点的一个极大子图,显然任意两个点都可以在一个会议中。然后的问题就是保证奇环。这里就要用到一个十分重要的性质:二分图中没有奇环。那么就可以判断一个图是否是二分图,如果不是,那么必然有一个奇环。然后利用这个奇环,对于这个图中的任意一点v可以构造出包括v的一个奇环(证明参见大白书P317)
关键:
分析出能参加会议的人必然在一个点双连通分量中
利用二分图判断图中存在奇环
图中存在奇环,那么对于任意一个点v,必然有包含v的奇环
判断双连通分量是否是二分图时对割点的处理
题意:
n个人开会,会议人数至少为三且为奇数。有些人相互憎恨,这些人不能邻座。统计有几个人不能参加任意一个会议
输入:n,m。m行包括两个整数k1、k2表示两个人相互憎恨。输入结束标志为n=m=0
输出:无法参加任何会议的人数
分析:
对于存在割点的图,割点两侧的人肯定不能在一个会议中(不能构成环)。而对于不存在割点的一个极大子图,显然任意两个点都可以在一个会议中。然后的问题就是保证奇环。这里就要用到一个十分重要的性质:二分图中没有奇环。那么就可以判断一个图是否是二分图,如果不是,那么必然有一个奇环。然后利用这个奇环,对于这个图中的任意一点v可以构造出包括v的一个奇环(证明参见大白书P317)
关键:
分析出能参加会议的人必然在一个点双连通分量中
利用二分图判断图中存在奇环
图中存在奇环,那么对于任意一个点v,必然有包含v的奇环
判断双连通分量是否是二分图时对割点的处理
const int MAXV = 1100; const int MAXE = 1000100; //无向图的双连通分量 int pre[MAXV], iscut[MAXV], bccno[MAXV], dfs_clock, bcc_cnt; // 割顶的bccno无意义 struct Edge { int u, v; }; vector<int> G[MAXV], bcc[MAXV]; stack<Edge> S; 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 = (Edge){u, v}; if(!pre[v]) // 没有访问过v { S.push(e); child++; int lowv = dfs(v, u); lowu = min(lowu, lowv); // 用后代的low函数更新自己 if(lowv >= pre[u]) { iscut[u] = true; bcc_cnt++; bcc[bcc_cnt].clear(); for(;;) { Edge x = S.top(); S.pop(); if(bccno[x.u] != bcc_cnt) { bcc[bcc_cnt].push_back(x.u); bccno[x.u] = bcc_cnt; } if(bccno[x.v] != bcc_cnt) { bcc[bcc_cnt].push_back(x.v); bccno[x.v] = bcc_cnt; } if(x.u == u && x.v == 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) { // 调用结束后S保证为空,所以不用清空 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 color[MAXV]; bool bipartite(int u, int b) { REP(i, G[u].size()) { 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; } bool can[MAXV][MAXV]; bool odd[MAXV]; int main() { // freopen("in.txt", "r", stdin); int n, kase; while (~RII(n, kase) && n) { CLR(can, true); CLR(odd, false); REP(i, n) G[i].clear(); REP(i, kase) { int a, b; RII(a, b); a--; b--; can[a][b] = can[b][a] = false; } REP(i, n) FF(j, i + 1, n) if (can[i][j]) { G[i].push_back(j); G[j].push_back(i); } find_bcc(n); int ans = 0; FE(i, 1, bcc_cnt) { //主要是处理割点 REP(j, bcc[i].size()) bccno[bcc[i][j]] = i; color[bcc[i][0]] = 1; if (!bipartite(bcc[i][0], i)) { REP(j, bcc[i].size()) { odd[bcc[i][j]] = true; color[bcc[i][j]] = 0; } } REP(j, bcc[i].size()) color[bcc[i][j]] = 0; } REP(i, n) if (!odd[i]) ans++; WI(ans); } return 0; }
相关文章推荐
- poj 2942 Knights of the Round Table 补图+点双连通分量+判定二分图
- PKU 2942 Knights of the Round Table - 无向图的块 判断奇圈
- POJ 2942 - Knights of the Round Table(点双联通+二分图)
- POJ 2942 Knights of the Round Table
- uva 1364 - Knights of the Round Table(二分图+强连通)
- POJ2942:Knights of the Round Table
- POJ 2942 Knights of the Round Table 点重连通分量+交叉染色判奇圈
- poj 2942 Knights of the Round Table Tarjan求点双联通分量+黑白染色二分图判断
- poj Knights of the Round Table 点双连通分量
- Knights of the Round Table--POJ 2942
- POJ 2942 Knights of the Round Table
- UVALive - 3523 Knights of the Round Table(无向图的双连通分量)
- UVA 10195 - The 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,无向图点双联通,二分图判定
- UVA1364 Knights of the Round Table
- [省选前题目整理][POJ 2942]Knights of the Round Table(Tarjan求点双联通分量+DFS对环染色)
- POJ 2942 Knights of the Round Table
- Knights of the Round Table