「POJ2942」Knights of the Round Table

把能坐在一起的连边,求出点双连通分量,再对每个点双连通分量判一下是否存在奇环。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<vector>
 4 #include<queue>
 5 #include<cstring>
 6 using namespace std;
 7 const int N=1010,M=1000010;
 8 int n,m,color[N];
 9 bool hate[N][N],can[N];
10 int dfn[N],low[N],timer,cnt,sta[N],top;
11 vector<int>tog[N];
12 void tarjan(int k,int fa){
13     dfn[k]=low[k]=++timer;
14     sta[top++]=k;
15     for(int i=1;i<=n;i++)if(!hate[k][i]){
16         if(fa==i) continue;
17         if(!dfn[i]){
18             tarjan(i,k);
19             low[k]=min(low[k],low[i]);
20             if(dfn[k]<=low[i]){
21                 cnt++;
22                 while(sta[top]!=i) top--,tog[cnt].push_back(sta[top]);;
23                 tog[cnt].push_back(k);
24             }
25         }else if(dfn[k]>dfn[i]) low[k]=min(low[k],dfn[i]);
26     }
27     if(!fa){
28         cnt++;
29         while(top){top--;tog[cnt].push_back(sta[top]);}
30     }
31     return;
32 }
33 inline bool pd(int k,int x){
34     for(int i=0;i<tog[k].size();i++) if(tog[k][i]==x)return 1;
35     return 0;
36 }
37 bool check(int k){
38     if(tog[k].size()==1) return 0;
39     memset(color,0,sizeof(color));
40     queue<int>q;
41     q.push(tog[k][0]);
42     color[tog[k][0]]=1;
43     int now;
44     while(!q.empty()){
45         now=q.front();q.pop();
46         for(int i=1;i<=n;i++) if(!hate[now][i]&&pd(k,i)){
47             if(!color[i]){
48                 color[i]=-1*color[now];
49                 q.push(i);
50             }else if(color[i]==color[now]) return 1;
51         }
52     }
53     return 0;
54 }
55 inline void reset(){
56     for(int i=1;i<=cnt;i++) tog[i].clear();
57     memset(dfn,0,sizeof(dfn));
58     memset(low,0,sizeof(low));
59     memset(hate,0,sizeof(hate));
60     memset(can,0,sizeof(can));
61     cnt=timer=0;
62     return;
63 }
64 void solve(){
65     if(!n) exit(0);
66     int t1,t2,ans=0;
67     for(int i=1;i<=m;i++) scanf("%d%d",&t1,&t2),hate[t1][t2]=hate[t2][t1]=1;
68     for(int i=1;i<=n;i++) hate[i][i]=1;
69     for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,0);
70     for(int i=1;i<=cnt;i++) if(check(i))
71         for(int j=0;j<tog[i].size();j++) can[tog[i][j]]=1;
72     for(int i=1;i<=n;i++) if(!can[i]) ans++;
73     printf("%d
",ans);
74     reset();
75     return;
76 }
77 int main(){
78     while(scanf("%d%d",&n,&m)) solve();
79     return 0;
80 }
原文地址:https://www.cnblogs.com/mycups/p/8527906.html