[HDU5452]Minimum Cut

来源:互联网 发布:js jquery name选择器 编辑:程序博客网 时间:2024/06/05 21:21
Problem Description
Given a simple unweighted graph G(an undirected graph containing no loops nor multiple edges) with nodes and edges. Let Tbe a spanning tree of .
We say that a cut in 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 (1t5which is the number of test cases.
Then test cases follow.
Each test case contains several lines.
The first line contains two integers n (2n20000and m (n1m200000).
The following nlines describe the spanning tree T and each of them contains two integers and corresponding to an edge.
Next mn+lines describe the undirected graph and each of them contains two integers 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 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;}