Problem Description
Given a simple unweighted graph G(an undirected graph containing no loops nor multiple edges) with n nodes and m edges. Let Tbe 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
Recommend
wange2014
题意:
给定一张n个点,m条边的无向图,并给出它的一棵生成树 。你需要删去一些边,使得剩下的图不连通,且删去的边中必须恰好包含一条树边。 求最少删去的边数。
题解:
枚举树上的每一条边,将其删掉后,树分裂成了两部分,必须删掉所有横跨两部分的非树边。
对于每条非树边,给树上对应路径上的边的答案都加 1。实现路径覆盖次数加1:在树上做差分。对于路径u-v,再点u和点v上+1,在其LCA上-2。
#include<iostream> #include<cstring> #include<cstdio> #include<cstdlib> #include<cmath> #include<algorithm> using namespace std; const int INF=0x7f7f7f7f; const int N=20010; const int M=400010; int T, n, m; void Getin( int &shu ) { char c; int f=1; shu=0; for( c=getchar(); c<'0' || c>'9'; c=getchar() ) if( c=='-' ) f=-1; for( ; c>='0' && c<='9'; c=getchar() ) shu=shu*10+c-'0'; shu*=f; } int fir[N], ecnt; struct nodes{ int e, next; }edge[M]; void Link( int s, int e ) { edge[++ecnt].e=e; edge[ecnt].next=fir[s]; fir[s]=ecnt; edge[++ecnt].e=s; edge[ecnt].next=fir[e]; fir[e]=ecnt; } int fa[N], son[N], dep[N], siz[N]; void DFS1( int r, int f, int d ) { dep[r]=d; siz[r]=1; for( int i=fir[r]; i; i=edge[i].next ) if( edge[i].e!=f ) { DFS1( edge[i].e, r, d+1 ); siz[r]+=siz[ edge[i].e ]; if( siz[ edge[i].e ]>siz[ son[r] ] ) son[r]=edge[i].e; fa[ edge[i].e ]=r; } } int top[N]; void DFS2( int r, int f ) { if( son[r] && son[r]!=r ) top[ son[r] ]=top[r], DFS2( son[r], r ); for( int i=fir[r]; i; i=edge[i].next ) if( edge[i].e!=f && edge[i].e!=son[r] ) { top[ edge[i].e ]=edge[i].e; DFS2( edge[i].e, r ); } } int LCA( int p1, int p2 ) { while( top[p1]!=top[p2] ) { if( dep[ top[p1] ]>dep[ top[p2] ] ) p1=fa[ top[p1] ]; else p2=fa[ top[p2] ]; } return dep[p1]<dep[p2] ? p1 : p2; } int cnt[N]; void DFS( int r, int f ) { for( int i=fir[r]; i; i=edge[i].next ) if( edge[i].e!=f ) { DFS( edge[i].e, r ); cnt[r]+=cnt[ edge[i].e ]; } } void Reset() { ecnt=0; memset( fir, 0, sizeof fir ); memset( cnt, 0, sizeof cnt ); memset( son, 0, sizeof son ); } int s, e, cas; int main() { for( Getin(T); T; T-- ) { Reset(); Getin(n); Getin(m); for( int i=1; i<n; i++ ) { Getin(s); Getin(e); Link( s, e ); } DFS1( 1, -1, 1 ); top[1]=1; DFS2( 1, -1 ); for( int i=n; i<=m; i++ ) { Getin(s); Getin(e); int f=LCA( s, e ); cnt[s]++; cnt[e]++; cnt[f]-=2; } DFS( 1, -1 ); int ans=INF; for( int i=2; i<=n; i++ ) ans=min( ans, cnt[i]+1 ); printf( "Case #%d: %d\n", ++cas, ans ); } return 0; }
[HDU5452]Minimum Cut
最新推荐文章于 2020-09-14 21:36:15 发布