UVALIVE 3523 双连通分量+二分图染色
来源:互联网 发布:捷联惯导速度算法 编辑:程序博客网 时间:2024/06/05 05:37
题目链接:https://vjudge.net/problem/18122
题意:
有n个骑士经常举行圆桌会议,每次圆桌会议至少要有3个骑士参加(且每次参加的骑士数量是奇数个),且所有
互相憎恨的骑士不能坐在圆桌旁的相邻位置,问有多少个骑士不可能参加任何一个会议
解法:
这题最终转化为求解图中结点是在一个奇圈上。首先我们可以把所有的圈找出来,即找到所有的双连通分量,
跑一边tarjan算法即可。之后重头戏来了,我们获得一个双连通块之后,怎么判断块中的点是不是在一个奇圈
上?答案——二分图染色!
定理:一个图为二分图的充分必要条件是图中不存在奇圈。
因此,如果一个双连通块为二分图,则不存在奇圈;如果一个双连通块不是二分图,则一定存在奇圈。但是这
样还有一个问题,我们能否保证所有非二分图双连通块的结点都在一个奇圈上?答案也是可以的。
可以这么想,因为块中一定存在一个奇圈,又因为块双连通,即任意结点u到结点v必存在两条点不重复路径,
那么假设v在奇圈上,我们考虑u到v的两条路径:若u也在一个奇圈上,则u在一个奇圈上的条件满足;若u在
一个偶圈上,则u到v必然存在一奇一偶两条路径,则可以形成一个新的奇圈。因此,双连通块中的结点u必然
在一个奇圈上。
///UVALIVE 5135#include <bits/stdc++.h>using namespace std;const int maxn = 2010;const int maxm = 1000010;struct Edge{ int u, v; Edge(int u=0, int v=0):u(u),v(v){}}e[maxm];int n,m,stamp,dfn[maxn],low[maxn],iscut[maxn],bccno[maxn];int scnt,stk[maxm],bcc_cnt;vector<int>vec[maxn],bcc[maxn];void tarjan(int index, int fa){ int child=0,tmp; dfn[index]=low[index]=++stamp; for(int i=0; i<vec[index].size(); i++){ tmp=e[vec[index][i]].v; if(!dfn[tmp]){ stk[++scnt]=vec[index][i], child++; tarjan(tmp,index); low[index]=min(low[index],low[tmp]); if(low[tmp]>=dfn[index]){ iscut[index]=1; bcc[++bcc_cnt].clear(); while(1){ int num=stk[scnt--]; if(bccno[e[num].u]!=bcc_cnt){ bcc[bcc_cnt].push_back(e[num].u); bccno[e[num].u]=bcc_cnt; } if(bccno[e[num].v]!=bcc_cnt){ bcc[bcc_cnt].push_back(e[num].v); bccno[e[num].v]=bcc_cnt; } if(e[num].u==index&&e[num].v==tmp) break; } } } else if(dfn[tmp]<dfn[index]&&tmp!=fa){ stk[++scnt]=vec[index][i]; low[index]=min(low[index],dfn[tmp]); } } if(fa<0&&child==1){ iscut[index]=0; }}void find_bcc(){ memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); memset(iscut, 0, sizeof(iscut)); memset(bccno, 0, sizeof(bccno)); memset(bcc, 0, sizeof(bcc)); stamp=scnt=bcc_cnt=0; for(int i=1; i<=n; i++){ if(!dfn[i]){ tarjan(i,-1); } }}int odd[maxn], color[maxn], b;bool dfs(int index,int c){ if(bccno[index]!=b) return 1; color[index]=c; for(int i=0;i<vec[index].size();i++) { int tmp=e[vec[index][i]].v; if(color[index]==color[tmp]) return 0; if(!color[tmp]&&!dfs(tmp,3-c)) return 0; } return 1;}int A[maxn][maxn];int main(){ while(scanf("%d%d", &n,&m)!=EOF&&n+m){ for(int i=1; i<=n; i++) vec[i].clear(); memset(A, 0, sizeof(A)); for(int i=0; i<m; i++){ int u,v; scanf("%d%d", &u,&v); A[u][v]=A[v][u]=1; } int len=0; for(int i=1; i<=n; i++){ for(int j=i+1; j<=n; j++){ if(!A[i][j]){ e[len]=Edge(i,j); vec[i].push_back(len++); e[len]=Edge(j,i); vec[j].push_back(len++); } } } find_bcc(); memset(odd, 0, sizeof(odd)); for(int i=1; i<=bcc_cnt; i++){ memset(color, 0, sizeof(color)); b=i; for(int j=0;j<bcc[i].size();j++) bccno[bcc[i][j]]=i; if(!dfs(bcc[i][0], 1)) for(int j=0;j<bcc[i].size();j++) odd[bcc[i][j]]=1; } int ans=0; for(int i=1; i<=n; i++){ if(!odd[i]){ ans++; } } printf("%d\n", ans); } return 0;}
0 0
- UVALIVE 3523(双连通分量+二分图染色)
- UVALIVE 3523 双连通分量+二分图染色
- poj 2942 双连通分量+二分图的染色判断
- poj 2942 点双连通分量+二分图染色
- poj2942 双连通分量+求奇圈二分染色
- UVALive 3523Knights of the Round Table(二分图+双连通分量)
- 【tarjan求双连通分量+染色判二分图】POJ 2942
- poj2942圆桌骑士(点双连通分量+二分图染色法判奇圈)
- POJ 2942 Knights of the Round Table [二分图染色][点双连通分量]
- [POJ]2942 圆桌骑士 点双连通分量 + 二分图染色
- #UVALive3523#Knights of the Round Table(点双连通分量 + 二分图染色判奇环)
- 双连通分量,二分图(圆桌骑士,LA 3523)
- poj2942[补图+点双连通分量+交叉染色法判定二分图(奇圈判定)]
- POJ 2942 Knights of the Round Table (点-双连通分量 + 交叉法染色判二分图)
- UVA 1364 - Knights of the Round Table (找双连通分量 + 二分图染色法判断)
- UVALive - 3523 Knights of the Round Table(无向图的双连通分量)
- UVALive 6044(双连通分量的应用)
- 双连通分量入门——UVALive
- (自用对各位没有价值)Java存储过程
- 模块
- Android手机连接到TOmcat服务器
- Java 集合之List 集合的添加方法顺序分析以及add和addAll区别
- 设置eclipse中xml的默认编辑器、行数、xsd和dtd
- UVALIVE 3523 双连通分量+二分图染色
- liunx下编译安装LNMP环境
- SpringBoot+Junit Test
- QT事件处理(二) 之 事件过滤器
- BZOJ 1787: [Ahoi2008]Meet 紧急集合/1832: [AHOI2008]聚会 LCA
- SQL优化总结
- eclipse打开xml文件都显示为灰色
- 算法训练 删除数组零元素
- python学习笔记 过滤文件