http://poj.org/problem?id=3177
题意:有n个牧场,互相连通,现在要求使得任意两个牧场之间至少有两条道路可走,求至少需要修多少条新的路
----------------------------------------
求出双连通分量中,度为1的个数ans,答案即为(ans+1)/2
----------------------------------------
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <algorithm> 5 #include <stack> 6 using namespace std; 7 const int N = 1e5 + 50; 8 int vis[N], low[N], dfn[N], cnt[N], belong[N]; 9 bool mp[5050][5050]; 10 int E, deep, n, m, cnt2; 11 stack<int>stk; 12 void dfs(int u, int fa) 13 { 14 vis[u] = 1; //在栈中 15 stk.push(u); 16 low[u] = dfn[u] = ++deep; 17 for (int i = 1; i <= n; i++) 18 { 19 if (mp[u][i] && i != fa) 20 { 21 if (!vis[i]){ 22 dfs(i, u); 23 low[u] = min(low[u], low[i]); 24 } 25 else 26 low[u] = min(low[u], dfn[i]); 27 } 28 } 29 if (low[u] == dfn[u] && vis[u]){ 30 cnt2++; //双连通分量个数 31 while (stk.top() != u){ 32 vis[stk.top()] = 0; 33 belong[stk.top()] = cnt2; 34 stk.pop(); 35 } 36 vis[u] = 0; 37 belong[u] = cnt2; 38 stk.pop(); 39 } 40 } 41 int main(){ 42 while (scanf("%d%d", &n, &m) != EOF) 43 { 44 E = deep = 0; 45 memset(low, 0, sizeof(low)); 46 memset(dfn, 0, sizeof(dfn)); 47 memset(vis, 0, sizeof(vis)); 48 memset(cnt, 0, sizeof(cnt)); 49 memset(belong, 0, sizeof(belong)); 50 while (stk.size())stk.pop(); 51 cnt2 = 0; 52 for (int i = 1; i <= m; i++) 53 { 54 int u, v; 55 scanf("%d%d", &u, &v); 56 mp[u][v] = mp[v][u] = 1; 57 } 58 dfs(1, 1); 59 for (int i = 1; i <= n; i++) 60 for (int j = 1; j <= n; j++) 61 if (mp[i][j] && belong[i] != belong[j]) //遍历所有边,度++ 62 cnt[belong[i]]++, cnt[belong[j]]++, mp[i][j] = mp[j][i] = 0; 63 int ans = 0; 64 for (int i = 1; i <= cnt2; i++) 65 if (cnt[i] == 1) ans++; 66 cout << (ans + 1) / 2 << endl; 67 } 68 }