uva 10972 RevolC FaeLoN cdoj 方老师和农场

//自己写的第一发tarjan

解:先进行双连通分解并缩点,分解后一定是一颗树,设叶节点个数为n那么答案就是(n+1)/2

关于双连通分量求解:在跑tarjan时判断每个点连向父节点的边是否是桥,如果是桥的话,该点的后代
中,未被染色的节点一点构成一个双连通分量,那么将其染色。

染色完成后依次检查每一条边的两端是
否为两种不同的颜色,如果是,所对应的颜色的度+1,最后看多少个度为1的节点就知道有多少叶子节点
也就能得到答案了。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<queue>
  8 #include<vector>
  9 #include<map>
 10 #include<stack>
 11 #include<string>
 12 
 13 using namespace std;
 14 
 15 const int MAXN=100007;
 16 const int MAXM=100007;
 17 
 18 vector<int> G[MAXN];
 19 int n,m,top,cnt1,cnt2;
 20 bool vis[MAXN];
 21 int color[MAXN],dfn[MAXN],low[MAXN];
 22 int stk[MAXN];
 23 int degree[MAXN];
 24 
 25 void tarjan(int now,int fa){
 26     cnt1++;
 27     dfn[now]=low[now]=cnt1;
 28     vis[now]=1;
 29     stk[top++]=now;
 30     int sz=G[now].size();
 31     for (int i=0;i<sz;i++){
 32             if (G[now][i]==fa) continue;
 33             if (!vis[G[now][i]]){
 34                     tarjan(G[now][i],now);
 35                     low[now]=min(low[now],low[G[now][i]]);
 36                     if (low[G[now][i]]>dfn[now]){
 37                             cnt2++;
 38                             while (top>0){
 39                                     color[stk[--top]]=cnt2;
 40                                     if (stk[top]==G[now][i]) break;
 41                             }
 42                     }
 43             }
 44             else{
 45                     low[now]=min(low[now],dfn[G[now][i]]);
 46             }
 47     }
 48 }
 49 
 50 int main(){
 51     while (scanf("%d%d",&n,&m)==2){
 52     cnt1=cnt2=top=0;
 53     memset(vis,0,sizeof(vis));
 54     memset(degree,0,sizeof(degree));
 55     memset(color,0,sizeof(color));
 56     memset(dfn,0,sizeof(dfn));
 57     memset(low,0,sizeof(low));
 58     memset(stk,0,sizeof(stk));
 59     for (int i=1;i<=n;i++){
 60             G[i].clear();
 61     }
 62     for (int i=0;i<m;i++){
 63             int x,y;
 64             scanf("%d%d",&x,&y);
 65             G[x].push_back(y);
 66             G[y].push_back(x);
 67     }
 68     for (int i=1;i<=n;i++){
 69             if (dfn[i]==0) tarjan(i,-1);
 70     }
 71     if (cnt2==1){
 72             printf("0\n");
 73             continue;
 74     }
 75     for (int i=1;i<=n;i++){
 76             int sz=G[i].size();
 77             for (int j=0;j<sz;j++){
 78                     if (color[i]!=color[G[i][j]]){
 79                             degree[color[i]]++;
 80                     }
 81             }
 82     }
 83     int ans=0;
 84     for (int i=1;i<=cnt2;i++){
 85             if (degree[i]==0) ans+=2;
 86             if (degree[i]==1) ans+=1;
 87     }
 88     printf("%d\n",(ans+1)/2);
 89     }
 90     return 0;
 91 }
 92 /*
 93 7 7
 94 1 2
 95 2 3
 96 3 4
 97 2 5
 98 4 5
 99 5 6
100 5 7
101 
102 3 3
103 1 2
104 2 3
105 1 3
106 
107 
108 7 5
109 1 2
110 2 3
111 4 5
112 5 6
113 5 7
114 */

 

posted @ 2015-06-03 22:46  鼠宝宝  阅读(142)  评论(0编辑  收藏  举报