poj 2942 双连通分量+二分图的染色判断
2016-05-21 16:52
417 查看
这道题是一道综合性比较强的图论题,题意是
亚瑟王要在圆桌上召开骑士会议,为了不引发骑士之间的冲突,并且能够让会议的议题有令人满意的结果,每次开会前都必须对出席会议的骑士有如下要求:
1、 相互憎恨的两个骑士不能坐在直接相邻的2个位置;
2、 出席会议的骑士数必须是奇数,这是为了让投票表决议题时都能有结果。
如果出现有某些骑士无法出席所有会议(例如这个骑士憎恨所有的其他骑士),则亚瑟王为了世界和平会强制把他剔除出骑士团。
现在给定准备去开会的骑士数n,再给出m对憎恨对(表示某2个骑士之间使互相憎恨的),问亚瑟王至少要剔除多少个骑士才能顺利召开会议?
注意:1、所给出的憎恨关系一定是双向的,不存在单向憎恨关系。
2、由于是圆桌会议,则每个出席的骑士身边必定刚好有2个骑士。即每个骑士的座位两边都必定各有一个骑士。
3、一个骑士无法开会,就是说至少有3个骑士才可能开会。
我的理解是是先判断割点,然后再利用二分图无奇圈的性质判断连通分量是否为偶圈,给出一组比较难过的测试数据:
代码如下:
亚瑟王要在圆桌上召开骑士会议,为了不引发骑士之间的冲突,并且能够让会议的议题有令人满意的结果,每次开会前都必须对出席会议的骑士有如下要求:
1、 相互憎恨的两个骑士不能坐在直接相邻的2个位置;
2、 出席会议的骑士数必须是奇数,这是为了让投票表决议题时都能有结果。
如果出现有某些骑士无法出席所有会议(例如这个骑士憎恨所有的其他骑士),则亚瑟王为了世界和平会强制把他剔除出骑士团。
现在给定准备去开会的骑士数n,再给出m对憎恨对(表示某2个骑士之间使互相憎恨的),问亚瑟王至少要剔除多少个骑士才能顺利召开会议?
注意:1、所给出的憎恨关系一定是双向的,不存在单向憎恨关系。
2、由于是圆桌会议,则每个出席的骑士身边必定刚好有2个骑士。即每个骑士的座位两边都必定各有一个骑士。
3、一个骑士无法开会,就是说至少有3个骑士才可能开会。
我的理解是是先判断割点,然后再利用二分图无奇圈的性质判断连通分量是否为偶圈,给出一组比较难过的测试数据:
6 8 1 4 1 5 1 6 2 4 2 5 2 6 3 6 4 5 0 0
代码如下:
#include<iostream> #include<cstring> #include<cstdio> using namespace std; #define MAXN 1004 #define MAXM 1001000 #define min(a,b) (a)<(b)?(a):(b) int n,m,tot,count,top; int first[MAXN],DFN[MAXN],Low[MAXN],vis[MAXN],col[MAXN],mark[MAXN],stack[MAXM],odd[MAXN]; int G[MAXN][MAXN]; struct Edge { int st,to,next,vis; }edge[2*MAXM]; void addedge(int a,int b) { edge[tot].to=b; edge[tot].st=a; edge[tot].next=first[a]; edge[tot].vis=0; first[a]=tot++; } int find(int s) { int i; for(i=first[s];i!=-1;i=edge[i].next) { int t=edge[i].to; if(mark[t]) { if(col[t]==-1) { col[t]=!col[s]; return find(t); } else if(col[t]==col[s]) return 1; } } return 0; } void color(int s) { int i; memset(mark,0,sizeof(mark)); do{ i=stack[top--]; mark[edge[i].st]=1; mark[edge[i].to]=1; }while(edge[i].st!=s); memset(col,-1,sizeof(col)); col[s]=0; if(find(s)) { for(i=1;i<=n;i++) { if(mark[i]) odd[i]=1; } } } void dfs(int s) { int i,v; DFN[s]=Low[s]=++count; for(i=first[s];i!=-1;i=edge[i].next) { v=edge[i].to; if(edge[i].vis)continue; edge[i].vis=edge[i^1].vis=1; stack[++top]=i; if(!DFN[v]) { dfs(v); Low[s]=min(Low[s],Low[v]); //到此可以判断是否形成局部图中的一个双联通分量 if(Low[v]>=DFN[s])color(s); //判断割点,并进入连通分量 } else { Low[s]=min(Low[s],DFN[v]); } } } int main() { while(scanf("%d%d",&n,&m),n||m) { int i,j; memset(G,0,sizeof(G)); for(i=1;i<=m;i++) { int a,b; scanf("%d%d",&a,&b); G[a][b]=1; G[b][a]=1; } tot=0; memset(first,-1,sizeof(first)); for(i=1;i<=n;i++) { for(j=i+1;j<=n;j++) { if(G[i][j]==0) { addedge(i,j); addedge(j,i); } } } memset(DFN,0,sizeof(DFN)); memset(odd,0,sizeof(odd)); count=0;top=0; for(i=1;i<=n;i++) { if(!DFN[i]) dfs(i); } int ans=0; for(i=1;i<=n;i++) { if(!odd[i]) ans++; } printf("%d\n",ans); } return 0; }
相关文章推荐
- 快速排序8
- java cache过期策略两种实现,一个基于list轮询一个基于timer定时
- HTML转义为实体,实体转回为HTML,特殊字符转换
- GridView监听器
- bzoj1529 [POI2005]ska Piggy banks
- TCP/IP入门(4) --应用层
- LeetCode Linked List Cycle II
- DH算法证明及相应的理论知识
- C# winform windows服务安装与卸载
- [从头学python] 第07节 numpy的盘点
- TCP/IP入门(3) --传输层
- 高可用,和负载均衡的简单理解
- TCP/IP入门(2) --网络层
- 机器学习入门学习资源
- 蓝桥杯 算法提高 日期计算
- 使用Handler下载数据
- 每天一个Linux命令(23)chmod命令
- useBean、setProperty、getProperty的用法
- TCP/IP入门(1) --链路层
- 刻在英国威斯敏斯特大教堂的一块墓碑上的话