POJ 2942--Knights of the Round Table(双连通分量)
来源:互联网 发布:逆袭网络剧第三集土豆 编辑:程序博客网 时间:2024/06/08 04:17
题意:有N个骑士,其中某些骑士互相憎恨对方,问要能使奇数个骑士开圆桌会议(憎恨的对方不能在一起)最少需要开除多少人?
题解:注意题意不是要求只开一次使人数达到最大的会议,而是删除那些永远不可能参加圆桌会议的人。
- 易知根据输入建立骑士能坐在一起的无向图(不一定连通)。
- 求出所有双连通分量,可参考本博对Tarjan论文的翻译。
- 在双连通分量里找是否有奇数个点的环(参考CSDN小优),若能找到奇圈,说明双连通分量的点都能参加圆桌会议(可能不是一次会议),对所有人做标记。
- 统计不能参加会议的人数输出。
*输入较大,使用读优化&G++时间可极大优化。
#include<iostream>#include<cstdio>#include<cstring>using namespace std;#define maxN 1005#define maxE 500000int N;char graph[maxN][maxN]; //无向连通图char NoExpelled[maxN]; //驱逐表(1代表能参加会议)char bcc[maxN][maxN]; //双连通分量图char IsInBcc[maxN]; //双连通分量点集char color[maxN]; //染色表int number[maxN]; //点的深搜发现时间int low[maxN]; //在深搜palm tree(树边和后向边集合)中此点能到达的最早点标号int index; //全局发现时间int stackTop; //边栈大小struct edge{ short x,y;};edge edgeStack[maxE];bool checkOddCircle(short u){ for(short v = 1;v <= N;v++) { if(bcc[u][v]) { if(color[v] != -1) { if(color[u] == color[v]) //找到奇圈则返回真 return true; } else { color[v] = !color[u]; if(checkOddCircle(v)) //直到找到奇圈才返回,若没找到则要继续遍历双连通分量 return true; } } } return false;}int BiConnect(short v,short u) //u is the father of v in spanning T{ number[v] = low[v] = index++; for(short w = 1;w <= N;w++) { if(w != u&&w != v&&graph[v][w]) //可行边并且不能是其本身以及其父节点 { edge newEdge; newEdge.x = v; newEdge.y = w; if(!number[w]) //w还没标记,则w将是v的一个子节点 { edgeStack[stackTop++] = newEdge; //将边压入栈 BiConnect(w,v); //继续深搜 low[v] = min(low[v],low[w]); //深搜返回后调整low值 if(low[w] >= number[v]) //有双连通分量或者桥边 { memset(color,0XFF,sizeof(color)); memset(bcc,0,sizeof(bcc)); memset(IsInBcc,0,sizeof(IsInBcc)); while((--stackTop)&&(edgeStack[(stackTop)].x != newEdge.x||edgeStack[(stackTop)].y != newEdge.y)) //将直到(v,w)的边出栈 { bcc[edgeStack[stackTop].x][edgeStack[stackTop].y] = 1; //将边保存到双连通分量bcc IsInBcc[edgeStack[stackTop].x] = IsInBcc[edgeStack[stackTop].y] = 1; //记录双连通分量中的点 } bcc[edgeStack[stackTop].x][edgeStack[stackTop].y] = 1; IsInBcc[edgeStack[stackTop].x] = IsInBcc[edgeStack[stackTop].y] = 1; color[v] = 0; if(checkOddCircle(v)) { for(int i = 1;i <= N;i++) //有奇圈则记录奇圈中的点 { if(IsInBcc[i]) { NoExpelled[i] = 1; } } } } } else if(number[w] < number[v]) //(v,w)是后向边,说明有环路 { edgeStack[stackTop++] = newEdge; low[v] = min(low[v],number[w]); } } } return 0;}int init(){ memset(graph,1,sizeof(graph)); //初始化图中所有点均连接 memset(NoExpelled,0,sizeof(NoExpelled)); memset(number,0,sizeof(number)); return 0;}int calcNum(){ int num = 0; for(short i = 1;i <= N;i++) { if(!NoExpelled[i]) { num++; } } return num;}int main(){ freopen("C:\\Users\\ifuding\\Desktop\\input.txt","r",stdin); int M; int x,y; while(~scanf("%d%d",&N,&M)&&N) { init(); while(M--) { scanf("%d%d",&x,&y); graph[x][y] = graph[y][x] = 0; } for(int i = 1;i <= N;i++) { if(!number[i]) { index = 1; stackTop = 0; BiConnect(i,0); } } printf("%d\n",calcNum()); } return 0;}
0 0
- poj 2942 Knights of the Round Table 双连通分量
- POJ 2942 Knights of The Round Table <双连通分量>
- 【双连通分量】 POJ Knights of the Round Table
- poj Knights of the Round Table 点双连通分量
- poj 2942 Knights of the Round Table (点双连通分量求解)
- poj 2942 Knights of the Round Table 圆桌骑士(双连通分量模板题)
- POJ 2942--Knights of the Round Table(双连通分量)
- poj 2942 Knights of the Round Table(点双连通分量)
- poj 2942 Knights of the Round Table(边双连通分量)
- poj 2942--Knights of the Round Table (点双连通分量)
- POJ 2942 Knights of the Round Table(【点双连通分量】+【二分图判定】)
- POJ 2942—— Knights of the Round Table双连通分量+交叉染色
- POJ 2942 Knights of the Round Table 边双连通分量求解
- poj 2942 Knights of the Round Table(双连通分量+tarjan+二分图判定)
- POJ 2942 Knights of the Round Table 点的双连通分量 + 奇圈
- POJ 2942 Knights of the Round Table 黑白着色+点双连通分量
- POJ 2942 Knights of the Round Table(双连通分量+二分图)
- poj 2942 Knights of the Round Table 补图+点双连通分量+判定二分图
- NGUI在3D场景中点击穿透解决办法
- 产品原型 UI 设计工具
- [PHP]PHP中memcache扩展的安装
- cryptdb 安装测试
- java 面试题算法
- POJ 2942--Knights of the Round Table(双连通分量)
- Silverlight IP地址控件
- (MVC)从客户端中检测到有潜在危险的 Request.Form 值
- IOS开发中的使用
- Toque 3D文档:介绍(目录浏览)
- 树莓派安装配置(从零开始)B+
- missing artifact jdk.tools 的解决方案
- 关于内容营销的3个误区 被分享≠被阅读
- zoj 3820 Building Fire Stations The 2014 ACM-ICPC Asia Mudanjiang Regional Contest bfs