对于图中每个点,记为k,求k到树中每个点的最大值(即树中的最大距离)
多组输入
Sample Input
5
1 1
2 1
3 1
1 1
Sample Output
3
2
3
4
4
我们不可能是把每一个点都搜索一次来找距离该点的最大距离,这样必然会超时,所以我们需要仔细分析一下。一开始随意找个点搜索一次,找出距离该点最大的点,这个点就是直径的一个端点,那我们反过来思考,是不是距离每个点的最大距离一定都是直径的端点呢,那这是不是意味着我们只要先找到直径的两个端点,然后用直径的两个端点进行搜索,对每个点的距离取一个最大值就可以找到最优解呢?
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<map>
using namespace std;
const int N=25003;
int n,idx,j,c,dist,v1,v2;
int d1[N],d2[N],d[N];
int e[N],ne[N],w[N],h[N];
void add(int a,int b,int c){
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int father){
for(int i=h[u];i!=-1;i=ne[i]){
int j=e[i];
if(j==father)continue;//防止原路返回
d[j]=d[u]+w[i];
dfs(j,u);
}//d数组维护每个点到u的距离
}//比如d[k]为k到u的距离
signed main(){
while(~scanf("%d",&n)){
memset(d1,0,sizeof d1);
memset(d2,0,sizeof d2);
memset(e,0,sizeof e);
memset(ne,0,sizeof ne);
memset(w,0,sizeof w);
memset(h,-1,sizeof h);//加边之前初始化
for(int i=2;i<=n;i++){
scanf("%d%d",&j,&c);
add(i,j,c);
add(j,i,c);
}
memset(d,0,sizeof d);
dist=0;
//任意找一个点记为k
//更新k点到所有点的距离
dfs(1,0);
//找距离k最远的点v1
for(int i=1;i<=n;i++){
if(d[i]>dist){
dist=d[i];
v1=i;
}
}
memset(d,0,sizeof d);
dist=0;
//更新v1到所有点的距离
dfs(v1,0);
for(int i=1;i<=n;i++)d1[i]=d[i];//d1记录v1到每个点的距离
//找直径的第二个端点v2
for(int i=1;i<=n;i++){
if(d[i]>dist){
dist=d[i];
v2=i;
}
}
memset(d,0,sizeof d);
dfs(v2,0);
for(int i=1;i<=n;i++)d2[i]=d[i];//d2记录v2到每个点的距离
for(int i=1;i<=n;i++)printf("%d\n",max(d1[i],d2[i]));
}
return 0;
}