Minimum Cut
Time Limit: 3000/2000 MS (Java/Others) Memory Limit: 65535/102400 K (Java/Others)
Total Submission(s): 769 Accepted Submission(s): 340
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.
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.
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
题意:在G中有T,问G 最小割中有且仅有一割在 T 中的最小割是多少。
考虑每条不属 于 T 边 对 生成树 T 树 边 的覆盖次数。
每条树边被覆盖的次数其实就是断裂这条树边后还需断裂的新边数。
在m-n-1行中都是T中没有的边,添加了(u, v)之后,v中的子节点,叶子节点都可以和u联系,那么在求最小割的时候就要删除这条边,使得G中 变成两个由 u 和v 构成的不连通的图。
用cnt 存该点需要被断裂几次,即断裂这条边后 还需要断裂几条边可以使G 不连通。遍历求最小值即最小割
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #include <cmath> 8 #include <stack> 9 #include <cstring> 10 11 using namespace std; 12 13 #define INF 0x3f3f3f3f 14 #define min(a,b) (a<b?a:b) 15 #define N 100005 16 17 vector< vector<int> > G; 18 int deep[N], f[N], cnt[N]; 19 20 void dfs(int u, int fa, int step) 21 { 22 deep[u] = step; 23 cnt[u] = 1; 24 f[u] = fa; 25 int len = G[u].size(); 26 for(int i = 0; i < len; i++) 27 { 28 int v = G[u][i]; 29 if(v != fa) 30 dfs(v, u, step+1); 31 } 32 } 33 34 void Lca(int x, int y) 35 { 36 while(x != y) 37 { 38 if(deep[x] >= deep[y]) 39 { 40 cnt[x]++; 41 x = f[x]; 42 } 43 else 44 { 45 cnt[y]++; 46 y = f[y]; 47 } 48 } 49 } 50 51 int main() 52 { 53 int t, i, a, b, n, m, l = 1; 54 scanf("%d", &t); 55 while(t--) 56 { 57 G.resize(N); 58 G.clear(); 59 scanf("%d%d", &n, &m); 60 for(i = 1; i < n; i++) 61 { 62 scanf("%d%d", &a, &b); 63 G[a].push_back(b); 64 G[b].push_back(a); 65 } 66 dfs(1, 0, 1); 67 for(; i <= m; i++) 68 { 69 scanf("%d%d", &a, &b); 70 Lca(a, b); 71 } 72 int ans = INF; 73 for(i = 2; i <= n; i++) 74 ans = min(ans, cnt[i]); 75 printf("Case #%d: %d ", l++, ans); 76 } 77 return 0; 78 }