Shirlies
宁静专注认真的程序媛~

将图变成双连通图,缩点,考虑该点与其他点相连的个数,如果只有一条边与其他点相连,则需要加一条边,因为这里面的点只能通过一条边到其他点,加一条边让它们能够通过另一条边到达其他点。

View Code
 1 #include <iostream>
 2 #include <cstring>
 3 #include <vector>
 4 using namespace std;
 5 
 6 const int maxN = 5000+10;
 7 int low[maxN];
 8 int DFN[maxN];
 9 int degree[maxN];
10 int cnt;
11 
12 vector<int> edge[maxN];
13 
14 void Tarjan(int x,int fa)
15 {
16     low[x] = DFN[x] = cnt ++;
17 
18     int len = edge[x].size();
19     for(int i = 0;i < len;i ++)
20     {
21         int u = edge[x][i];
22         if(u == fa) continue;
23         if(!DFN[u]) 
24         {
25             Tarjan(u,x);
26             if(low[x] > low[u]) low[x] = low[u];
27         }
28         else if(low[x] > DFN[u])
29         {
30             low[x] = DFN[u];
31         }
32     }
33 }
34 
35 void UseTarjan()
36 {
37     memset(DFN,0,sizeof(DFN));
38     cnt = 1;
39 
40     Tarjan(1,1);
41 }
42 
43 bool isok(int x,int value)
44 {
45     int len = edge[x].size();
46     for(int i = 0;i < len;i ++)
47         if(edge[x][i] == value)
48             return false;
49 
50     return true;
51 }
52 
53 int main()
54 {
55     int n,m;
56 
57     cin >> n >> m;
58     for(int i = 0;i < m;i ++)
59     {
60         int u,v;
61         cin >> u >> v;
62         if(isok(u,v))
63         {
64         edge[u].push_back(v);
65         edge[v].push_back(u);
66         }
67     }
68 
69     UseTarjan();
70     
71     memset(degree,0,sizeof(degree));
72     for(int i = 1;i <= n;i ++)
73     {
74         int len = edge[i].size();
75         for(int j = 0;j < len;j ++)
76         {
77             if(low[i] != low[edge[i][j]])
78             {
79                 degree[low[i]] ++;
80                 //degree[low[edge[i][j]]] ++;
81             }
82         }
83     }
84 
85     int ans = 0;
86     for(int i = 1;i < cnt;i ++)
87     {
88         if(degree[i] == 1) ans++;
89     }
90 
91     cout << (ans + 1) / 2 << endl;
92 
93     return 0;
94 }
posted on 2012-09-13 21:19  Shirlies  阅读(159)  评论(0编辑  收藏  举报