Warm up

Time Limit: 5000ms
Memory Limit: 65535KB
This problem will be judged on HDU. Original ID: 4612
64-bit integer IO format: %I64d      Java class name: Main
  N planets are connected by M bidirectional channels that allow instant transportation. It's always possible to travel between any two planets through these channels.
  If we can isolate some planets from others by breaking only one channel , the channel is called a bridge of the transportation system.
People don't like to be isolated. So they ask what's the minimal number of bridges they can have if they decide to build a new channel.
  Note that there could be more than one channel between two planets.
 

Input

  The input contains multiple cases.
  Each case starts with two positive integers N and M , indicating the number of planets and the number of channels.
  (2<=N<=200000, 1<=M<=1000000)
  Next M lines each contains two positive integers A and B, indicating a channel between planet A and B in the system. Planets are numbered by 1..N.
  A line with two integers '0' terminates the input.
 

Output

  For each case, output the minimal number of bridges after building a new channel in a line.
 

Sample Input

4 4
1 2
1 3
1 4
2 3
0 0

Sample Output

0

Source

 
解题:类似于network那题。。。边双连通+树的直径
此题严重爆栈。。。只能用微软的编译器
 
HDU 4612 Warm up_边双连通HDU 4612 Warm up_#include_02
 1 #pragma comment(linker, "/STACK:102400000,102400000")
 2 #include <iostream>
 3 #include <queue>
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <stack>
 7 using namespace std;
 8 const int maxn = 200010;
 9 struct arc{
10     int to,next;
11     arc(int x = 0,int y = -1){
12         to = x;
13         next = y;
14     }
15 }e[4000000];
16 int head[maxn],hd[maxn],dfn[maxn],low[maxn],belong[maxn];
17 int scc,idx,tot,n,m,d[maxn];
18 bool instack[maxn];
19 stack<int>stk;
20 void add(int *head,int u,int v){
21     e[tot] = arc(v,head[u]);
22     head[u] = tot++;
23 }
24 void tarjan(int u,int fa){
25     dfn[u] = low[u] = ++idx;
26     instack[u] = true;
27     stk.push(u);
28     bool flag = true;
29     for(int i = head[u]; ~i; i = e[i].next){
30         if(e[i].to == fa && flag){
31             flag = false;
32             continue;
33         }
34         if(!dfn[e[i].to]){
35             tarjan(e[i].to,u);
36             low[u] = min(low[u],low[e[i].to]);
37         }else if(instack[e[i].to]) low[u] = min(low[u],dfn[e[i].to]);
38     }
39     if(low[u] == dfn[u]){
40         scc++;
41         int v;
42         do{
43             instack[v = stk.top()] = false;
44             stk.pop();
45             belong[v] = scc;
46         }while(v != u);
47     }
48 }
49 void init(){
50     for(int i = 0; i < maxn; ++i){
51         head[i] = hd[i] = -1;
52         belong[i] = low[i] = dfn[i] = 0;
53         instack[i] = false;
54     }
55     idx = scc = tot = 0;
56     while(!stk.empty()) stk.pop();
57 }
58 queue<int>q;
59 int bfs(int u){
60     while(!q.empty()) q.pop();
61     memset(d,-1,sizeof(d));
62     d[u] = 0;
63     q.push(u);
64     while(!q.empty()){
65         u = q.front();
66         q.pop();
67         for(int i = hd[u]; ~i; i = e[i].next){
68             if(d[e[i].to] == -1){
69                 d[e[i].to] = d[u] + 1;
70                 q.push(e[i].to);
71             }
72         }
73     }
74     int maxV = 0,idx = u;
75     for(int i = 1; i <= scc; ++i)
76         if(d[i] > maxV) maxV = d[idx = i];
77     return idx;
78 }
79 int main(){
80     int u,v;
81     while(scanf("%d %d",&n,&m),n||m){
82         init();
83         for(int i = 0; i < m; ++i){
84             scanf("%d %d",&u,&v);
85             add(head,u,v);
86             add(head,v,u);
87         }
88         tarjan(1,-1);
89         for(int i = 1; i <= n; ++i)
90         for(int j = head[i]; ~j; j = e[j].next){
91             if(belong[i] != belong[e[j].to])
92                 add(hd,belong[i],belong[e[j].to]);
93         }
94         printf("%d\n",scc - 1 - d[bfs(bfs(1))]);
95     }
96     return 0;
97 }
View Code

 

很容易想到树的直径就是某一点到两个最长点的和。。。

HDU 4612 Warm up_边双连通HDU 4612 Warm up_#include_02
 1 #pragma comment(linker, "/STACK:102400000,102400000")
 2 #include <iostream>
 3 #include <queue>
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <stack>
 7 using namespace std;
 8 const int maxn = 200010;
 9 struct arc {
10     int to,next;
11     arc(int x = 0,int y = -1) {
12         to = x;
13         next = y;
14     }
15 } e[4000000];
16 int head[maxn],dfn[maxn],low[maxn],belong[maxn];
17 int scc,idx,tot,n,m,dp[maxn][2];
18 bool instack[maxn];
19 stack<int>stk;
20 void add(int *head,int u,int v) {
21     e[tot] = arc(v,head[u]);
22     head[u] = tot++;
23 }
24 void tarjan(int u,int fa) {
25     dfn[u] = low[u] = ++idx;
26     instack[u] = true;
27     stk.push(u);
28     dp[u][0] = dp[u][1] = 0;
29     bool flag = true;
30     for(int i = head[u]; ~i; i = e[i].next) {
31         if(e[i].to == fa && flag) {
32             flag = false;
33             continue;
34         }
35         if(!dfn[e[i].to]) {
36             tarjan(e[i].to,u);
37             low[u] = min(low[u],low[e[i].to]);
38             int tmp = dp[e[i].to][1] + (low[e[i].to] > dfn[u]);
39             if(tmp > dp[u][1]) {
40                 swap(dp[u][1],dp[u][0]);
41                 dp[u][1] = tmp;
42             } else if(tmp > dp[u][0]) dp[u][0] = tmp;
43         } else if(instack[e[i].to]) low[u] = min(low[u],dfn[e[i].to]);
44     }
45     if(low[u] == dfn[u]) {
46         scc++;
47         int v;
48         do {
49             instack[v = stk.top()] = false;
50             stk.pop();
51             belong[v] = scc;
52         } while(v != u);
53     }
54 }
55 void init() {
56     for(int i = 0; i < maxn; ++i) {
57         head[i] = -1;
58         belong[i] = low[i] = dfn[i] = 0;
59         instack[i] = false;
60     }
61     idx = scc = tot = 0;
62     while(!stk.empty()) stk.pop();
63 }
64 int main() {
65     int u,v;
66     while(scanf("%d %d",&n,&m),n||m) {
67         init();
68         for(int i = 0; i < m; ++i) {
69             scanf("%d %d",&u,&v);
70             add(head,u,v);
71             add(head,v,u);
72         }
73         tarjan(1,-1);
74         int ans = 0;
75         for(int i = 1; i <= n; ++i)
76             ans = max(ans,dp[i][1] + dp[i][0]);
77         printf("%d\n",scc - 1 - ans);
78     }
79     return 0;
80 }
View Code

 

夜空中最亮的星,照亮我前行