POJ2942
来源:互联网 发布:大数据新能源建设 编辑:程序博客网 时间:2024/05/16 15:37
Problem : Knights of the Round Table
Description :
有N个要围着圆桌武士开会,敌对关系的武士不能坐在一起。而且,一个桌子上的武士人数必须是奇数。现在问你最少要开除多少武士才能开会。
Solution :
点双连通分量+二分图奇圈判定+标记。这个题目我参考了这位大牛的博客和刘汝佳的书。
首先我们要建立补图,把能坐在一起的武士连边。然后求一个点双连通分量,因为点双连通分量内部点总有两条节点不重复的路径,其实就是类似环。这也符合了圆桌的背景,左边一个人,右边一个人。
其次就是要判定奇圈了,假设点双连通分量中含有奇圈,但是整个分量中的点数是偶数,那么这几个人是不是可以在一起开会呢?答案是可以的,看下图:
整个图示一个点连通分量,点v 不在奇圈中,但是根据点双连通图的性质,v 一定可以到达u1 和u2 ,而且这两条路径不重复。那么u1−>u2 的两条路径必然有一条是奇数有一条是偶数,因为u1 ,u2 是在同一个奇圈中的,那么必然可以构造一个新的奇圈包括v ,看下图就理解了。由于我是第一次写二分图的染色判定,因此直接按照上面大牛的写法来写了,但是发现不对,因为染色判定如果发现同色那么就立即返回,一个点扩展的所有结点都不同色才能返回true。下面我贴出来了这两种写法。
这个题做了一天,启示也是挺深的。
Code(C++) :
#include <stdio.h>#include <string.h>#include <stdlib.h>#include <stack>#define MAX(a,b) ((a)>(b)? (a):(b))#define MIN(a,b) ((a)<(b)? (a):(b))typedef struct tagEdge{ int from,to; tagEdge(){} tagEdge(int from,int to):from(from),to(to){} bool operator==(const tagEdge &o)const{ return from==o.from&&to==o.to; }}Edge;using namespace std;const int M=1000+5;int dfn[M],low[M];bool map[M][M],G[M][M];bool is_same_bcc[M];int color[M];int bcc[2*M],num;bool ans[M];int n,m;int num_dfn;stack<Edge> sta;bool bicoloring(int x,int c){ color[x]=c; for(int i=1;i<=n;i++) if(map[x][i]&&is_same_bcc[i]){ if(!color[i]){ if(!bicoloring(i,3-c)) return false; } else if(color[i]==color[x]) return false; } return true;}void dfs(int from,int fa){ dfn[from]=low[from]=++num_dfn; for(int to=1;to<=n;to++) if(map[from][to]){ if(to!=fa&&dfn[to]<dfn[from]){ if(!dfn[to]){ Edge EE=Edge(from,to); sta.push(EE); dfs(to,from); low[from]=MIN(low[from],low[to]); if(dfn[from]<=low[to]){ num=0; memset(is_same_bcc,false,sizeof(is_same_bcc)); memset(color,0,sizeof(color)); for(Edge tmp=sta.top();;tmp=sta.top()){ sta.pop(); bcc[num++]=tmp.from; bcc[num++]=tmp.to; is_same_bcc[tmp.from]=true; is_same_bcc[tmp.to]=true; if(tmp==EE||sta.empty()) break; } if(!bicoloring(bcc[0],1)){ for(int i=0;i<num;i++) ans[bcc[i]]=true; } } }else low[from]=MIN(low[from],dfn[to]); } }}int main(){ //freopen("in.data","r",stdin); while(scanf("%d%d",&n,&m),n+m){ memset(G,false,sizeof(G)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(ans,false,sizeof(ans)); for(int i=1;i<=n;i++) G[i][i]=true; int x,y; for(int i=1;i<=m;i++){ scanf("%d%d",&x,&y); G[x][y]=G[y][x]=true; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) map[i][j]=(G[i][j]==false); num_dfn=0; for(int i=1;i<=n;i++) if(!dfn[i]) dfs(i,-1); int sum=0; for(int i=1;i<=n;i++) sum+=(int)ans[i]; printf("%d\n",n-sum); } return 0;}
0 0
- poj2942
- POJ2942
- poj2942
- poj2942解题报告
- poj2942 解题报告
- poj2942 圆桌骑士
- poj2942 双连通分量+求奇圈二分染色
- POJ2942--Knights of the Round Table
- poj2942 点双连通分量
- 【图的连通性】poj2942圆桌骑士
- poj2942 Knights of the Round Table
- poj2942 Knights of the Round Table
- poj2942 Knights of the Round Table
- POJ2942-Knights of the Round Table
- poj2942(双联通分量,交叉染色判二分图)
- poj2942 点双连通图分量+二分图判定
- poj2942圆桌骑士【点双连通分量+二分图判断】
- poj2942:Knights of the Round Table(Tarjan)
- NavigationView修改菜单item项的布局参数
- CSS】怎么解决浏览器兼容性问题
- CTP源码分析1 CTP结构及概述
- php数组函数
- android 手机应用设备管理激活状态,获取激活状态,监听激活状态
- POJ2942
- Python性能鸡汤
- ffmpeg的tutorial中文版学习笔记(三)
- 关于iOS开发入门的一些建议
- CSS样式-链接
- UCOSIII事件标志组
- java Pattern和Matcher详解
- spring如何下载
- 回溯法基础--案例