Minimum Cut
Time Limit: 3000/2000 MS (Java/Others) Memory Limit: 65535/102400 K (Java/Others)
Total Submission(s): 315 Accepted Submission(s): 120
Problem Description
Given a simple unweighted graph G (an undirected graph containing no loops nor multiple edges) with n nodes and m edges. Let T be a spanning tree of G.
We say that a cut in G respects T if it cuts just one edges of T.
Since love needs good faith and hypocrisy return for only grief, you should find the minimum cut of graph G respecting the given spanning tree T.
Input
The input contains several test cases.
The first line of the input is a single integer t (1≤t≤5) which is the number of test cases.
Then t test cases follow.
Each test case contains several lines.
The first line contains two integers n (2≤n≤20000) and m (n−1≤m≤200000).
The following n−1 lines describe the spanning tree T and each of them contains two integers u and v corresponding to an edge.
Next m−n+1 lines describe the undirected graph G and each of them contains two integers u and v corresponding to an edge which is not in the spanning tree T.
Output
For each test case, you should output the minimum cut of graph G respecting the given spanning tree T.
Sample Input
1
4 5
1 2
2 3
3 4
1 3
1 4
Sample Output
Case #1: 2
Source
2015 ACM/ICPC Asia Regional Shenyang Online
解题:先把树建好,添加非树边,会形成环,把环上的非树边都+1,最后树上的最小边+1就是答案
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 20010; 4 struct arc { 5 int to,next; 6 arc(int x = 0,int y = -1) { 7 to = x; 8 next = y; 9 } 10 } e[500100]; 11 int head[maxn],fa[maxn],top[maxn],de[maxn]; 12 int siz[maxn],son[maxn],loc[maxn],c[maxn],tot,clk; 13 void add(int u,int v) { 14 e[tot] = arc(v,head[u]); 15 head[u] = tot++; 16 } 17 void FindHeavyEdge(int u,int father,int depth) { 18 fa[u] = father; 19 siz[u] = 1; 20 son[u] = -1; 21 de[u] = depth; 22 for(int i = head[u]; ~i; i = e[i].next) { 23 if(e[i].to == father) continue; 24 FindHeavyEdge(e[i].to,u,depth + 1); 25 siz[u] += siz[e[i].to]; 26 if(son[u] == -1 || siz[e[i].to] > siz[son[u]]) 27 son[u] = e[i].to; 28 } 29 } 30 void ConnectHeavyEdge(int u,int ancestor) { 31 top[u] = ancestor; 32 loc[u] = clk++; 33 if(son[u] != -1) ConnectHeavyEdge(son[u],ancestor); 34 for(int i = head[u]; ~i; i = e[i].next) { 35 if(e[i].to == fa[u] || son[u] == e[i].to) continue; 36 ConnectHeavyEdge(e[i].to,e[i].to); 37 } 38 } 39 void update(int u,int v) { 40 while(top[u] != top[v]) { 41 if(de[top[u]] < de[top[v]]) swap(u,v); 42 c[loc[top[u]]]++; 43 c[loc[u] + 1]--; 44 u = fa[top[u]]; 45 } 46 if(u == v) return; 47 if(de[u] > de[v]) swap(u,v); 48 c[loc[son[u]]]++; 49 c[loc[v]+1]--; 50 } 51 int main() { 52 int kase,u,v,n,m,cs = 1; 53 scanf("%d",&kase); 54 while(kase--) { 55 memset(head,-1,sizeof head); 56 memset(c,0,sizeof c); 57 tot = clk = 0; 58 scanf("%d%d",&n,&m); 59 for(int i = 1; i < n; ++i) { 60 scanf("%d%d",&u,&v); 61 add(u,v); 62 add(v,u); 63 } 64 FindHeavyEdge(1,0,0); 65 ConnectHeavyEdge(1,1); 66 for(int i = 0; i <= m - n; ++i) { 67 scanf("%d%d",&u,&v); 68 update(u,v); 69 } 70 int ret = 0x3f3f3f3f; 71 for(int i = 1; i < clk; ++i) { 72 c[i] += c[i-1]; 73 ret = min(ret,c[i]); 74 } 75 printf("Case #%d: %d\n",cs++,ret + 1); 76 } 77 return 0; 78 }