LA 3523 Knights of the Round Table(点双连通分量+二分图判断)
2016-07-24 15:37
471 查看
题意:有n个骑士经常举行圆桌会议,商讨大事,每次圆桌会议至少应有3个骑士参加,且互相憎恨的骑士不能坐在圆桌旁的相邻位置,如果发生意见分歧,则需要举手表决,因此参加会议的骑士数目必须是奇数,以防赞同和反对票一样多,知道哪些骑士互相憎恨之后,你的任务是统计有多少个骑士不可能参加任何一个会议。
分析:求出原图的补图后,问题转化为判断一个点是否存在一个奇数环内,一个环内的所有点一定在同一个点双连通分量内,我们求出所有的点双连通分量后,判断一下它是否为一个二分图,若不是二分图则连通分量内的所有点均至少存在一个奇环内。注意对割点染色时的特殊判断。
分析:求出原图的补图后,问题转化为判断一个点是否存在一个奇数环内,一个环内的所有点一定在同一个点双连通分量内,我们求出所有的点双连通分量后,判断一下它是否为一个二分图,若不是二分图则连通分量内的所有点均至少存在一个奇环内。注意对割点染色时的特殊判断。
#include <cstdio> #include <stack> #include <queue> #include <vector> #include <cstdio> #include <utility> #include <cstring> #include <iostream> #include <algorithm> #define INF 0x3f3f3f3f #define MOD 1000000007 using namespace std; int n,m,ans,bcc_cnt,dfs_clock,pre[1005],bccno[1005],low[1005],color[1005]; bool hate[1005][1005],isans[1005]; struct Edge { int u,v; Edge(int x,int y) { u = x; v = y; } }; stack <Edge> S; vector <int> bcc[1005]; int dfs(int u,int fa) { low[u] = pre[u] = ++dfs_clock; for(int v = 1;v <= n;v++) if(!hate[u][v]) { Edge e = Edge(u,v); if(!pre[v]) { S.push(e); low[u] = min(low[u],dfs(v,u)); if(low[v] >= pre[u]) { 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); low[u] = min(low[u],pre[v]); } } return low[u]; } bool jud(int u,int colm,int edg) { bool flag = true; color[u] = colm; for(int v = 1;v <= n;v++) if(!hate[u][v] && bccno[v] == edg) if(!color[v]) flag = flag && jud(v,3-colm,edg); else if(color[v] != 3-colm) return false; return flag; } int main() { while(scanf("%d%d",&n,&m) == 2) { if(n == 0 && m == 0) break; memset(hate,0,sizeof(hate)); memset(pre,0,sizeof(pre)); memset(bccno,0,sizeof(bccno)); memset(isans,0,sizeof(isans)); bcc_cnt = ans = 0; for(int i = 1;i <= n;i++) hate[i][i] = true; for(int i = 1;i <= m;i++) { int x,y; scanf("%d%d",&x,&y); hate[x][y] = hate[y][x] = true; } for(int i = 1;i <= n;i++) { dfs_clock = 0; if(!pre[i]) dfs(i,-1); } for(int i = 1;i <= bcc_cnt;i++) { memset(color,0,sizeof(color)); if(bcc[i].size() <= 2) continue; for(int u : bcc[i]) bccno[u] = i; bool flag = !jud(bcc[i][0],1,i); for(int u : bcc[i]) isans[u] = isans[u] || flag; } for(int i = 1;i <= n;i++) if(isans[i]) ans++; printf("%d\n",n-ans); } }
相关文章推荐
- 每日一省之————字符串排序算法(包括低位优先、高位优先、三向快速排序)
- web前端开发分享-css,js工具篇
- 【机器学习】朴素贝叶斯分类器
- 从指南针到动手搭建自己的第一台计算机
- Node.js中,获取req请求的原始IP
- Java解决No enclosing instance of type PrintListFromTailToHead is accessible问题的两种方案
- 子串和
- 更新与查询数据库
- eclipse4.2(juno)各种插件安装(j2ee,m2e,maven-svn,svn,hibe
- android开发 Activity包含Fragment切换背景黑色闪屏解决方案
- 提取data.frame中的部分数据(不含列标题和行标题)
- 【hihoCoder】1037 : 数字三角形
- socket原理详解
- Iptables防火墙知识总结
- Python学习笔记17:网络客户端编程
- Java开源Saas开发框架+Activiti流程管理=JSAAS
- vim 常用命令
- Java运行时数据区域学习
- 根据jsonobject中的部分数据更新javabean中对应的属性[PATCH]
- JAVASE总结--01(java 历史历程简述、JDK的安装、用CMD编译运行程序)