ZOJ - 3820 Building Fire Stations

来源:互联网 发布:航天信息开票软件下载 编辑:程序博客网 时间:2024/06/06 07:44

题意:给你一棵树求两个点使得树上所有点到这两个点路径长度的最小值最小


取直径的中点拆掉拆成两棵树,分别求两边的直径中点就是答案==QAQ细节真多==还会爆栈不开心


#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define rep(j,k,l) for (int j=k;j<=l;j++)#define N 400005using namespace std;int T,n,cnt,lft,rgt,to[N*2],ne[N*2],st[N],deep[N],miaom[3];int used[N],last[N],que[N];void add(int k,int l){to[++cnt]=l;ne[cnt]=st[k];st[k]=cnt;}int bfs(int k){int head=0,tail=1,_=k;memset(used,0,sizeof(used));used[k]=1;que[1]=k;deep[k]=1;last[k]=0;while (head<tail){int x=que[++head];for (int i=st[x];i;i=ne[i])if (used[to[i]]==0&&(!((x==lft||x==rgt)&&(x+to[i]==lft+rgt)))){que[++tail]=to[i];deep[to[i]]=deep[x]+1;if (deep[to[i]]>deep[_]) _=to[i];used[to[i]]=1;last[to[i]]=x;}}return _;}void init(){cnt=0;scanf("%d",&n);rep(i,1,n) st[i]=0;rep(i,1,n-1){int k,l;scanf("%d%d",&k,&l);add(k,l);add(l,k);}}int mddl(int k,int poi){int o=bfs(k);int p=bfs(o);miaom[poi]=deep[p]/2;for (int i=p;i;i=last[i])if (deep[i]==deep[p]+1-(deep[p]+1)/2) return i;}void solve(){lft=0;rgt=0;rgt=mddl(1,0);lft=last[rgt];int k=mddl(lft,1),l=mddl(rgt,2);lft=0;rgt=0;n=bfs(1);printf("%d %d %d\n",max(miaom[2],max(miaom[1],abs(deep[k]-deep[l])/2)),k,l);}int main(){scanf("%d",&T);while (T--){init();solve();}}


0 0
原创粉丝点击