POJ-2942-Knights of the Round Table
刘汝佳新书题
题意求是求不在任意一个简单奇圈的点的个数
先求双连通分量,再用二分图判断是否是奇圈
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <stack> using namespace std; #define MAXN 1005 int A[MAXN][MAXN]; int n,m; struct Edge{ int u,v; }; vector<int>G[MAXN],bcc[MAXN]; int pre[MAXN],iscut[MAXN],bccno[MAXN],dfs_clock,bcc_cnt; stack<Edge> S; int dfs(int u,int fa) { int lowu= pre[u]=++dfs_clock; int child=0; for(int i=0;i<G[u].size();i++) { int v=G[u][i]; Edge e; e.u=u,e.v=v; if(!pre[v]) { S.push(e); child++; int lowv=dfs(v,u); lowu=min(lowu,lowv); if(lowv>=pre[u]) { iscut[u]=1; bcc_cnt++; 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); lowu=min(lowu,pre[v]); } } if(fa<0&&child==1)iscut[u]=0; return lowu; } //双连通分量 void find_bcc(int n) { memset(pre,0,sizeof(pre)); memset(iscut,0,sizeof(iscut)); memset(bccno,0,sizeof(bccno)); dfs_clock=bcc_cnt=0; for(int i=0;i<n;i++) if(!pre[i])dfs(i,-1); } //判断二分图 int odd[MAXN],color[MAXN]; bool bipartite(int u,int b) { for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(bccno[v]!=b)continue; if(color[v]==color[u]) return false; if(!color[v]) { color[v]=3-color[u]; if(!bipartite(v,b))return false; } } return true; } int main() { while(scanf("%d%d",&n,&m)==2) { if(n==0&&m==0) break; for(int i=0;i<n;i++) G[i].clear(); int a,b; memset(A,0,sizeof(A)); for(int i=0;i<m;i++) { scanf("%d%d",&a,&b); a--,b--; A[b][a]=A[a][b]=1; } for(int i=0;i<n;i++) for(int j=i+1;j<n;j++) { if(A[i][j]) continue; G[i].push_back(j),G[j].push_back(i); } find_bcc(n); memset(odd,0,sizeof(odd)) ; for(int i=1;i<=bcc_cnt;i++) { memset(color,0,sizeof(color)); for(int j=0;j<bcc[i].size();j++) bccno[bcc[i][j]]=i; int u=bcc[i][0]; color[u]=1; if(!bipartite(u,i)) for(int j=0;j<bcc[i].size();j++) odd[bcc[i][j]]=1; } int ans=n; for(int i=0;i<n;i++) if(odd[i])ans--; printf("%d\n",ans); } return 0; }