Minimum Cut
Time Limit: 3000/2000 MS (Java/Others) Memory Limit: 65535/102400 K (Java/Others)
Total Submission(s): 2449 Accepted Submission(s): 1160
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
思路:题意是先给一棵树,然后在加一些无向边变成一个连通图,在只允许删除树中一条边的情况下删除最少边使图不连通。
如果光是一棵树的话只要删任意一条边就可以达到目标变成两个子树,所以各个点的ans都为1,后面每来一个边,都会使此边相连的两个点的到LCA上的所有点的ans++,因为要删这条新边两个子树才不连通。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=200010;
struct nod{
int to,next;
}e[maxn*2];
int deep[maxn];
int ans[maxn];
int fa[maxn];
int head[maxn];
int tot;
void add(int f,int t){
e[tot].to=t;
e[tot].next=head[f];
head[f]=tot++;
}
void dfs(int u,int fath,int dp){
deep[u]=dp;
ans[u]=1;
fa[u]=fath;
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].to;
if(v!=fath){
dfs(v,u,dp+1);
}
}
}
void lca(int x,int y){
while(x!=y){
if(deep[x]>=deep[y]){
ans[x]++;
x = fa[x];
}
else {
ans[y]++;
y=fa[y];
}
}
}
int main(){
int t,n,m,l;
scanf("%d",&t);
int cas=0;
while(t--){
tot=0;///init
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
int u,v;
for(int i=1;i<n;i++) {
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs(1,0,1);
for(int i=n;i<=m;i++) {
scanf("%d%d",&u,&v);
lca(u,v);
}
int res=0x3f3f3f3f;
for(int i=2;i<=n;i++) res=min(res,ans[i]);
printf("Case #%d: %d\n",++cas,res);
}
}