首页 > 代码库 > ZOJ-3820 Building Fire Stations 题解
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 题解
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。