HDU 2196 Computer



题目在这里

题意:

一棵树,对于其中的每个点,求与这个点距离最远的点的距离。

解法:

两次DFS。

第一次DFS时求出每个点的子树中的最远距离和次远距离(从下向上进行更新)。

第二次DFS时求出每个点的最远距离(从上向下进行更新;仔细分析就可以知道,一个点的最远距离只可能是由它的子树得到,或者从它的父结点的最长距离或者次长距离加上它与父节点的距离得到。)

#define debug
#define file
double  abcxx00;
#define  FF  cout<<"==================================input:", cin>>abcxx00;
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<sstream>
#include<string>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<vector>
#include<queue>
#include<stack>
#include<list>
#include<set>
#include<map>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
using namespace std;

const int maxn = 1e5 +5;
int n;
typedef pair<int,int> pii;
vector<pii>adj[maxn];
int disDown[maxn][2];  /// 0 for longest!!

void dfs1(int a, int fax){
    disDown[a][0] = disDown[a][1] = 0;
    int s,f,b;
    for(s=adj[a].size(),f=0; f < s; f++){
        b = adj[a].at(f).fi;
        if(b != fax){
            dfs1(b, a);
            int t = disDown[b][0]+adj[a].at(f).se;
            if(t >= disDown[a][0]){
                disDown[a][1] = disDown[a][0];
                disDown[a][0] = t;
            }
            else if(t > disDown[a][1]){
                disDown[a][1] = t;
            }
        }
    }
  //  printf("id:%d %d %d\n", a,disDown[a][0],disDown[a][1]);
}

void dfs2(int a, int fax){
    int s,f,b,lenn,t;
    for(s=adj[a].size(),f=0; f < s; f++){
        b = adj[a].at(f).fi;
        lenn = adj[a].at(f).se;
        if(b != fax){
            if(disDown[b][0]+lenn == disDown[a][0]){
                t = disDown[a][1]+lenn;
            }
            else{
                t = disDown[a][0]+lenn;
            }
            if(t >= disDown[b][0]){
                disDown[b][1] = disDown[b][0];
                disDown[b][0] = t;
            }
            else if(t > disDown[b][1]){
                disDown[b][1] = t;
            }
            dfs2(b, a);
        }
    }
//    printf("id:%d %d\n", a,disDown[a][0]);
}

void cyh(){
    dfs1(1, -1);
    dfs2(1, -1);
    for(int e=1; e <= n; e++){
        printf("%d\n", disDown[e][0]);
    }
}



int main(){
    int e,x,len;
    while(cin >> n){
        for(e=1; e <= n; e++){
            adj[e].clear();
        }
        for(e=2; e <= n; e++){
            scanf("%d %d", &x,&len);
            adj[e].pb(mp(x,len));
            adj[x].pb(mp(e,len));
        }
        cyh();
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值