poj2942Knights of the Round Table

http://poj.org/problem?id=2942

代码敲的迷迷糊糊的 照把书上的给搬上来的

给篇讲的不错的解题报告 各种定义都有 http://blog.csdn.net/lyy289065406/article/details/6756821

做这题之前 一定要把相关定义搞清楚 割点 双连通分量  二分图  奇圈

View Code
  1 #include <iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<stdlib.h>
  6 #include<stack>
  7 #include<vector>
  8 using namespace std;
  9 struct node
 10 {
 11     int u,v;
 12 };
 13 vector<int>G[1010],bcc[1010];
 14 int w[1010][1010],pre[1010],iscut[1010],bccno[1010],dc,bc,odd[1010],co[1010];
 15 stack<node>s;
 16 int dfs(int u,int fa)
 17 {
 18     int lowu  = pre[u]= ++dc;
 19     int child  =0,i;
 20     for(i = 0 ; i < G[u].size() ; i++)
 21     {
 22         int v = G[u][i];
 23         node e = (node){u,v};
 24         if(!pre[v])
 25         {
 26             s.push(e);
 27             child++;
 28             int lowv = dfs(v,u);
 29             lowu = min(lowv,lowu);
 30             if(lowv>=pre[u])
 31             {
 32                 bc++;
 33                 bcc[bc].clear();//将找到的双连通分量依次 存起来
 34                 iscut[u] = 1;
 35                 for(;;)
 36                 {
 37                     node x = s.top();
 38                     s.pop();
 39                     if(bccno[x.u]!=bc)
 40                     {
 41                         bcc[bc].push_back(x.u);
 42                         bccno[x.u] = bc;
 43                     }
 44                     if(bccno[x.v]!=bc)
 45                     {
 46                         bcc[bc].push_back(x.v);
 47                         bccno[x.v] = bc;
 48                     }
 49                     if(x.u==u&&x.v==v)
 50                         break;
 51                 }
 52             }
 53         }
 54         else if(pre[v]<pre[u]&&v!=fa)
 55         {
 56             s.push(e);
 57             lowu = min(lowu,pre[v]);
 58         }
 59     }
 60     if(fa<0&&child==1)
 61         iscut[u] = 0;//其实没看出来iscut有嘛用。。
 62     return lowu;
 63 }
 64 void find_bcc(int n)//找双连通分量
 65 {
 66     memset(pre,0,sizeof(pre));
 67     memset(iscut,0,sizeof(iscut));
 68     memset(bccno,0,sizeof(bccno));
 69     dc = bc = 0;
 70     for(int i = 1 ; i <= n ; i++)
 71         if(!pre[i])
 72             dfs(i,-1);
 73 }
 74 int bipart(int u,int b)//判断是不是二分图 着色法
 75 {
 76     int i;
 77     for(i = 0 ; i < G[u].size() ; i++)
 78     {
 79         int v = G[u][i];
 80         if(bccno[v]!=b) continue;
 81         if(co[v] == co[u])
 82         return 0;
 83         if(!co[v])
 84         {
 85             co[v] = 3-co[u];
 86             if(!bipart(v,b))
 87             return 0;
 88         }
 89     }
 90     return 1;
 91 }
 92 int main()
 93 {
 94     int i,j,k,n,m,g;
 95     while(cin>>n>>m)
 96     {
 97         if(n==0&&m==0)
 98             break;
 99         for(i = 1; i <= n ; i++)
100             G[i].clear();
101         memset(w,0,sizeof(w));
102         for(i = 1 ; i <= m ;i++)
103         {
104             int u,v;
105             scanf("%d%d",&u,&v);
106             w[u][v] = 1;
107             w[v][u] = 1;
108         }
109         for(i = 1; i <= n ; i++)
110             for(j = i+1 ; j <= n ; j++)
111                 if(!w[i][j])
112                 {
113                     G[i].push_back(j);
114                     G[j].push_back(i);
115                 }
116         find_bcc(n);
117         memset(odd,0,sizeof(odd));
118         for(i = 1 ; i <= bc ; i++)
119         {
120             memset(co,0,sizeof(co));
121             for(j = 0 ; j < bcc[i].size() ; j++)
122             bccno[bcc[i][j]] = i;//双连通分量的割顶
123             int u = bcc[i][0];
124             co[u] = 1;
125             if(!bipart(u,i))
126             {
127                 for(g =  0 ; g < bcc[i].size() ;g++)
128                 odd[bcc[i][g]] = 1;
129             }
130         }
131         int ans = 0;
132         for(i = 1 ; i <= n ; i++)//不在奇圈中的计数
133             if(!odd[i])
134             ans++;
135         cout<<ans<<endl;
136     }
137     return 0;
138 }
原文地址:https://www.cnblogs.com/shangyu/p/3024672.html