http://poj.org/problem?id=2942
题意 :n个骑士举行圆桌会议,每次会议应至少3个骑士参加,且相互憎恨的骑士不能坐在圆桌旁的相邻位置。如果意见发生分歧,则需要举手表决,因此参加会议的骑士数目必须是奇数,以防止赞同和反对的票一样多,知道哪些骑士相互憎恨之后,你的任务是统计有多少个骑士不可能参加任何一个会议。
思路 :这个题牵扯的知识点挺多的,具体的可以参考白书上解释的蛮详细的。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <stdio.h> #include <stack> #include <string.h> #include <algorithm> #include <vector> using namespace std; const int maxn = 1100 ; struct Edge { int u,v ; Edge(int u ,int v):u(u),v(v) {} } ; int pre[maxn],dfs_clock ,iscut[maxn],Bcc_cnt,Bccno[maxn] ; vector<int>G[maxn],Bcc[maxn] ; stack<Edge>S ; int odd[maxn],color[maxn] ; int A[maxn][maxn] ; 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 = (Edge) { u,v } ; if(!pre[v]) { S.push(e) ; child++ ; int lowv = dfs(v,u) ; lowu = min(lowu,lowv) ; if(lowv >= pre[u]) { iscut[u] = true ; 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) ; } 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() { int kase = 0,n,m ; while(scanf("%d %d",&n,&m) == 2 && n) { for(int i = 0 ; i < n ; i++ ) G[i].clear() ; memset(A,0,sizeof(A)) ; for(int i = 0 ; i < m ; i++) { int u,v ; scanf("%d %d",&u,&v) ; u-- ; v-- ; A[u][v] = A[v][u] = 1 ; } for(int u = 0 ; u < n ; u++) { for(int v = u+1 ; v < n ; v++) if(!A[u][v]) { G[u].push_back(v); G[v].push_back(u) ; } } 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 ",ans) ; } return 0; }