UVALive3523 [Knights of the Round Table] tarjan求无向图双联通分量
2017-08-25 13:39
639 查看
题目链接
题意:有n个骑士经常举行圆桌会议,商讨大事。每次圆桌会议至少应有3个骑士参加,且相互憎恨的骑士不能坐在圆桌旁的相邻位置。如果发生意见分歧,则需要举手表决,因为骑士不能保证每次提议都一致通过,因此参加会议的骑士数目必须是奇数,以防止赞同和反对票一样多。知道哪些骑士相互憎恨之后,你的任务是统计有多少个骑士不可能参加任何一个会议。
solution:
以骑士为节点建图(不互相憎恨的骑士之间连边,表示可以坐在相邻位置)
原问题就可以转化为求不在任意一个奇圈(节点有奇数个的圈)的点的数量
因为二分图不含奇圈,如果一个双联通分量是二分图,则只需要找出图中的
双联通分量,在判断是否为二分图,就可以算出答案了。
ps:含有奇圈的双联通分量中的每一个点都属于至少一个奇圈。
解释一下:
U1,U2 属于同一个奇圈
因为是双联通分量,所以v与U1,U2都连通。
因为是奇圈,所以U1到U2的两条路长度为一奇一偶。
所以无论黄线长为奇数或偶数,v,U1,U2组成的圈中一定有一个奇圈。
#include <stack> #include <vector> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> using namespace std; const int N = 1e3 + 7; struct Edge{ int u, v; }; stack<Edge> S; vector<int> G , bcc ; int dfn , low , pos , bcc_cnt, id; int col , odd ; void dfs(int u, int fa){ dfn[u]=low[u]=++id; for ( int i=0; i<G[u].size(); i++ ){ int v=G[u][i]; if( v==fa ) continue; Edge e=(Edge) { u, v }; if( !dfn[v] ){ S.push(e); dfs(v, u); low[u]=min(low[u], low[v]); if( dfn[u]<=low[v] ){ bcc[++bcc_cnt].clear(); for(;;){ Edge x=S.top(); S.pop(); if( pos[x.v]!=bcc_cnt ) {pos[x.v]=bcc_cnt; bcc[bcc_cnt].push_back(x.v); } if( pos[x.u]!=bcc_cnt ) {pos[x.u]=bcc_cnt; bcc[bcc_cnt].push_back(x.u); } if( x.u==u && x.v==v ) break; } } }else if( dfn[v]<low[u] ){ S.push(e); low[u]=min(low[u],dfn[v]); } } } void find_bcc(int n){ memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(pos,0,sizeof(pos)); bcc_cnt=id=0; for ( int i=1; i<=n; i++ ) if( !dfn[i] ) dfs(i, 0); } bool bipartite(int u, int b){ for ( int i=0; i<G[u].size(); i++ ){ int v=G[u][i]; if( pos[v]!=b ) continue; if( col[v]==col[u] ) return false; if( !col[v] ){ col[v]=3-col[u]; if( !bipartite(v, b) ) return false; } } return true; } int A ; int main(){ int n, m; while( scanf("%d%d", &n, &m )!=EOF &&n ){ for ( int i=0; i<=n; i++ ) G[i].clear(); memset(A,0,sizeof(A)); for ( int i=1; i<=m; i++ ){ int x, y; scanf("%d%d", &x, &y ); A[x][y]=A[y][x]=1; } // printf("\n"); for ( int i=1; i<=n; i++ ) for ( int j=i+1; j<=n; j++ ) if( !A[i][j] ) /*printf("%d %d\n", i, j),*/ G[i].push_back(j), G[j].push_back(i); find_bcc(n); // printf("\n"); /* for ( int i=1; i<=bcc_cnt; i++ ){ for ( int j=0; j<bcc[i].size(); j++ ) printf("%d ", bcc[i][j] ); printf("\n"); } */ memset(odd,0,sizeof(odd)); memset(pos,0,sizeof(pos)); // printf("\n"); for ( int i=1; i<=bcc_cnt; i++ ){ memset(col,0,sizeof(col)); for ( int j=0; j<bcc[i].size(); j++ ) pos[bcc[i][j]]=i; // printf("%d\n", bcc[i].size() ); int u=bcc[i][0]; col[u]=1; if( !bipartite(u,i)){ // printf("%d\n", i); for ( int j=0; j<bcc[i].size(); j++ ) odd[bcc[i][j]]=1; } // printf("\n"); } // printf("\n"); int ans=n; for ( int i=1; i<=n; i++ ) if( odd[i] ) ans--; printf("%d\n", ans ); } return 0; }
相关文章推荐
- UVALive - 3523 Knights of the Round Table(双联通分量)
- UVALive - 3523 Knights of the Round Table(无向图的双连通分量)
- UVAlive 3523 Knights of the Round Table [点双连通分量] [Tarjan]
- UVAlive3523 Knights of the Round Table(bcc)
- POJ 2942 Knights of the Round Table 补图+tarjan求点双联通分量+二分图染色+debug
- UVALive - 3523 Knights of the Round Table(【点双连通分量】+【二分图判定】)
- UVALive 3523 Knights of the Round Table(BCC+二分图)
- uvalive 3523 Knights of the Round Table 圆桌骑士(强连通+二分图)
- POJ 2942:Knights of the Round Table tarjan点双联通分量 二分图染色找奇环
- UVALive 3523 Knights of the Round Table 圆桌骑士 (无向图点双连通分量)
- UVAlive3523 Knights of the Round Table(bcc)
- uva1364 - Knights of the Round Table 点-双联通分量
- poj 2942 Knights of the Round Table Tarjan求点双联通分量+黑白染色二分图判断
- UVALive-3523 Knights of the Round Table (双连通分量+二分图匹配)
- [省选前题目整理][POJ 2942]Knights of the Round Table(Tarjan求点双联通分量+DFS对环染色)
- UVALive3523-Knights of the Round Table(BCC+二分图判定)
- UVALive 3523 Knights of the Round Table(二分图+双连通分量)
- 【POJ 2942】Knights of the Round Table(双联通分量+染色判奇环)
- POJ2942 Knights of the Round Table(双联通分量+奇圈判断)
- poj2942 Knights of the Round Table,无向图点双联通,二分图判定