[HDU5452]Minimum Cut

13 篇文章 0 订阅
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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值