您的位置:首页 > 其它

HDU 4612 Warm up 树的最长路径DP + 无向图带重边

2015-08-19 11:33 381 查看
Warm up

Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)

Problem Description

  N planets are connected by M bidirectional channels that allow instant transportation. It's always possible to travel between any two planets through these channels.

  If we can isolate some planets from others by breaking only one channel , the channel is called a bridge of the transportation system.

People don't like to be isolated. So they ask what's the minimal number of bridges they can have if they decide to build a new channel.

  Note that there could be more than one channel between two planets.

Input

  The input contains multiple cases.

  Each case starts with two positive integers N and M , indicating the number of planets and the number of channels.

  (2<=N<=200000, 1<=M<=1000000)

  Next M lines each contains two positive integers A and B, indicating a channel between planet A and B in the system. Planets are numbered by 1..N.

  A line with two integers '0' terminates the input.

Output

  For each case, output the minimal number of bridges after building a new channel in a line.

Sample Input

4 4

1 2

1 3

1 4

2 3

0 0

Sample Output

0

Author

SYSU

Source

2013 Multi-University Training Contest 2

Recommend

zhuyuanchen520

题意:给定N个点,M条边。求在该图加入一条边后,得到最少的桥数。

思路:首先,明确这是一个有重边无向图,选用邻接表实现;

其次,对原图进行深搜,形成的深搜树,记录割边数;

求最小桥数,即对于缩点后的无根树找最远点对。连接即为所有。

接着就是重点 找最远点对。对于找最远点对有两种实现方法:

1:2次DFS 任取节点U,用DFS求出U的最远节点v,再用一次DFS求最远节点w (v,w)就是最远点对。

2:DP 实现 dp(u) = max{dp(v)}+1 ;

具体实现就是对于节点u , 若存在桥(u,v) 则更新dp1(u) = max{dp(v)}+1 , 并记录次大值 dp2(u) = dp1(u) ;

若(u,v)不为桥 则dp1(u) = max{dp(v} 。具体实现看代码。

初始值dp1(u) = dp2(u) = 0 ;

设dp[maxn][2] 分别为该点到树两端的最远距离。

ANS = 桥数-最远距离

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define min(a,b) (a>b?b:a)
#define max(a,b) (a>b?a:b)
#define CLR(arr,x) memset(arr,x,sizeof(arr))
using namespace std;
const int maxn1 = 200000+100 ;
const int maxn2 = 2000000+100 ;
int n , m ;
int Times ,Nbridge , Num ;
int Low[maxn1] , Dfn[maxn1] ;
int dp[maxn1][2] ;
int head[maxn2] ;
struct Edge{
int v , next ;
}edge[maxn2];
void AddEdge( int from , int to ) {
edge[Num].v = to ;
edge[Num].next = head[from] ;
head[from] = Num++ ;

edge[Num].v = from ;
edge[Num].next = head[to] ;
head[to] = Num++ ;
}
void Tarjan(int u , int Number) {
Dfn[u] = Low[u] = ++Times;
dp[u][0] = dp[u][1]  = 0 ;
int temp = 0 ;
for( int e = head[u] ; e!= -1 ; e = edge[e].next ) {
int v = edge[e].v ;
if( (Number^1) == e ){continue ;}
if(!Dfn[v]) {
Tarjan(v,e) ;
Low[u] = min(Low[u],Low[v]) ;
temp = dp[v][0] ;
if( Low[v] > Dfn[u]) {
Nbridge++ ;
temp = dp[v][0]+1 ;
}
if(temp > dp[u][0]) {
dp[u][1] = dp[u][0] ;
dp[u][0] = temp ;
}
else if( temp > dp[u][1] ) {
dp[u][1] = temp ;
}
}
else {
Low[u] = min(Low[u],Dfn[v]) ;
}
}
}
void Init() {
CLR(Dfn,0) ;
CLR(head,-1) ;
CLR(dp,0) ;
Times = Nbridge = Num =  0;
}
int main() {
int e1 ,e2 ;
while(~scanf("%d%d",&n,&m)&&(n||m)) {
Init() ;
while(m--){
scanf("%d%d",&e1,&e2) ;
AddEdge(e1,e2) ;
}
Tarjan(1,-1) ;
int maxx = -1;
for( int i = 1 ; i <= n ; ++i) {
maxx = maxx>(dp[i][0] + dp[i][1]) ? maxx : (dp[i][0]+dp[i][1] ) ;
}
printf("%d\n",Nbridge-maxx) ;
}
return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: