ZOJ-3820 Building Fire Stations 题解

题目大意:

  一棵树,在其中找两个点,使得其他点到这两个的距离的较小值的最大值的最小值及其方案。

思路:

  首先显然一棵树的直径的中点到其他点的距离的最大值必定比其他点的小。

  那么感性思考一下就将一棵树的直径平分成两段,在找分成的两棵树的直径的中点。

  PS:dfs貌似要爆栈,用非递归或bfs。

代码:

 1 #include<cstdio>
 2 const int M=200005;
 3 int ed,cnt,fa[M],q[M],dep[M],v[M<<1],nex[M<<1],hea[M];
 4 bool vis[M];
 5 
 6 int read()
 7 {
 8     int x=0; char ch=getchar();
 9     while (ch<'0' || ch>'9') ch=getchar();
10     while (ch>='0' && ch<='9') x=(x<<1)+(x<<3)+ch-48,ch=getchar();
11     return x;
12 }
13 
14 void add(int x,int y) { v[++cnt]=y,nex[cnt]=hea[x],hea[x]=cnt; }
15 
16 void build(int s)
17 {
18     int h=0,t=1; fa[s]=0;
19     dep[q[1]=ed=s]=1;
20     while (h^t)
21     {
22         int x=q[++h],y,i;
23         for (i=hea[x];i;i=nex[i])
24             if (!vis[y=v[i]] && y^fa[x])
25             {
26                 dep[y]=dep[fa[q[++t]=y]=x]+1;
27                 if (dep[ed]<dep[y]) ed=y;
28             }
29     }
30 }
31 
32 void getdis(int x) { build(x); build(ed); }
33 
34 int main()
35 {
36     for (int T=read();T;--T)
37     {
38         int n=read(),ans,i,len,x,y,z;
39         for (cnt=i=0;i<=n;++i) hea[i]=0;
40         for (i=1;i<n;++i)
41         {
42             x=read(),y=read();
43             add(x,y),add(y,x);
44         }
45         getdis(1); len=dep[x=ed];
46         for (;dep[x]!=(len>>1)+1;x=fa[x]);
47         vis[x]=1; getdis(fa[x]); len=dep[y=ed];
48         for (;dep[y]!=(len>>1)+1;y=fa[y]);
49         ans=len>>1; vis[x]=0; vis[z=fa[x]]=1;
50         getdis(x); len=dep[ed]; vis[z]=0;
51         for (;dep[ed]!=(len>>1)+1;ed=fa[ed]);
52         len=len>>1; if (ans<len) ans=len;
53         printf("%d %d %d\n",ans,y,ed);
54     }
55     return 0;
56 }

 

转载于:https://www.cnblogs.com/HHshy/p/6160311.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值