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 */

 

你可能感兴趣的:(uva)