computer

对于图中每个点,记为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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值