ZOJ-3820 Building Fire Stations 题解
Posted SHYI
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
以上是关于ZOJ-3820 Building Fire Stations 题解的主要内容,如果未能解决你的问题,请参考以下文章
ZOJ Problem Set - 3820 Building Fire Stations 树的直径 + 操作
UVA - 11039 B - Building designing
D02 TED Elon Mulsk The future we're building — and boring
使用 Alamofire 从 Firebase 检索 JSON