bzoj2237[NCPC2009]Flight Planning 结论题?

2237: [NCPC2009]Flight Planning

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 55  Solved: 27
[Submit][Status][Discuss]

Description

S航空公司在N座城市之间有N-1条航线,航线是双向的。任意两座城市都是可以互相到达的,但是可能需要在一些城市换乘不同的航线。

目前有人抱怨要到达有些城市需要换乘太多次,S航空公司为了缓解这一现状,决定取消目前的一条航线,添加另一条航线,在保证任意两座城市还是可以互相到达的前提下,使得两座城市之间需要乘坐的航线次数的最大值最小。

Input

 

第一行为一个整数N(4<=N<=2500),表示城市的个数。城市从1到N编号。

接下来N-1行,每行是一对整数a和b,表示一条连接a和b的航线(1<=a,b<=N)。

 

Output

输出仅一行,即航空公司进行调整后,任意两座城市之间需要乘坐的航班次数的最大值。

 

Sample Input


4

1 2

2 3

3 4

Sample Output


2

【样例解释】

取消3-4的航线,添加2-4的航线。

HINT

 

对于100%的数据,N<=2500。

 

题意:在一棵树上,你可以任意删除一条边再加上一条并使得这个图还是颗树,在此前提下,你要让树的直径最小,求最小直径

n^2是可以接受的
枚举每一条边,把它断开,形成两个联通块,对这两个联通块求直径l1 l2
那么ans=min(ans,max(l1,l2,(l1+1)/2+(l2+1)/2+1))
简单说明一下后面那一坨:
对于两棵树,要把它们连起来后是直径最小,肯定是链接两颗树直径的中点
用反证法可以证明这样更优:假设选择另外的点链接,那么直径两端(a , b)到它的距离的max(disa,disb) 不会比到中点的距离短

 

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define N 2505
 6 using namespace std;
 7 int n,tot=1,l1,l2,hd[N],dis[N],x[N],y[N],ban[N<<1];
 8 struct edge{int u,v,next;}e[N<<1];
 9 void adde(int u,int v){
10     e[++tot].v=v;
11     e[tot].u=u;
12     e[tot].next=hd[u];
13     hd[u]=tot; 
14 }
15 void dfs(int u,int fa){
16     for(int i=hd[u];i;i=e[i].next){
17         int v=e[i].v;
18         if(v==fa||ban[i])continue;
19         dis[v]=dis[u]+1;
20         dfs(v,u); 
21     }
22 }
23 int getlen(int x){
24     int t1,t2;
25     memset(dis,0,sizeof(dis));
26     dfs(x,0);t1=x;
27     for(int i=1;i<=n;i++)
28     if(dis[i]>dis[t1])t1=i;
29     memset(dis,0,sizeof(dis));
30     dfs(t1,0);t2=t1;
31     for(int i=1;i<=n;i++)
32     if(dis[i]>dis[t2])t2=i;
33     return dis[t2];
34 }
35 int main(){
36     scanf("%d",&n);
37     for(int i=1;i<n;i++){
38         int u,v;
39         scanf("%d%d",&u,&v);
40         adde(u,v);adde(v,u); 
41     }int ans=1<<30;
42     for(int i=2;i<=tot;i+=2){
43         ban[i]=ban[i^1]=1;
44         l1=getlen(e[i].u);
45         l2=getlen(e[i].v);
46         ans=min(ans,max(l1,max(l2,(l1+1)/2+(l2+1)/2+1)));
47         ban[i]=ban[i^1]=0;
48     }printf("%d",ans);
49     return 0;
50 }

 

转载于:https://www.cnblogs.com/wsy01/p/8111084.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值