http://acm.hdu.edu.cn/showproblem.php?pid=2196
题意:开始输入 n ,表示有 n 个顶点,然后输入 n - 1 行,第 i 行两个数 x, y 表示 i, x有一条边, 路径长度为 y ,求每个点和离这个点距离最远的点之间的距离。
思路:用个数组dp[i][2]记录一下每个节点 i 的最远距离和次远距离。首先 dfs 一次,把每个点除父结点以外的的最远距离和次远距离求出来,然后再 dfs 一次把父结点方向的距离也加入到最远和次远距离中。
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long loli;
struct node{
int to;
int val;
node(int x = 0, int y = 0){
to = x;
val = y;
}
};
int n;
loli dp[10010][2];
vector<node> tr[10010];
loli Dfs_1(int rt, int pre) //求每个点除父结点方向以外的最远距离和次远距离
{
int len = tr[rt].size();
dp[rt][0] = dp[rt][1] = 0;
for(int i = 0; i < len; i++){
int son = tr[rt][i].to;
if(son == pre)
continue;
loli flag = Dfs_1(son, rt) + tr[rt][i].val;
if(flag > dp[rt][0]){ //更新最远距离
dp[rt][1] = dp[rt][0]; //最远变次远
dp[rt][0] = flag;
}
else if(flag > dp[rt][1]){ //更新次远距离
dp[rt][1] = flag;
}
}
return dp[rt][0];
}
int Dfs_2(int rt, int pre, loli sum) //sum 是父结点方向的最远距离
{
int len = tr[rt].size();
if(sum > dp[rt][0]){ //更新最远距离
dp[rt][1] = dp[rt][0]; //最远变次远
dp[rt][0] = sum;
}
else if(sum > dp[rt][1]){ //更新次远距离
dp[rt][1] = sum;
}
for(int i = 0; i < len; i++){
int son = tr[rt][i].to;
if(son == pre)
continue;
if(dp[son][0] + tr[rt][i].val == dp[rt][0]) //当前方向是最远距离
Dfs_2(son, rt, dp[rt][1] + tr[rt][i].val); //传递次远距离
else
Dfs_2(son, rt, dp[rt][0] + tr[rt][i].val); //不是最远距离方向
}
}
int main()
{
while(cin>>n){
int x, y;
for(int i = 0; i <= n; i++){
tr[i].clear();
}
for(int i = 2; i <= n; i++){
cin>>x>>y;
tr[i].push_back(node(x, y));
tr[x].push_back(node(i, y));
}
Dfs_1(1, -1);
Dfs_2(1, -1, 0);
for(int i = 1; i <= n; i++){
cout<<dp[i][0]<<endl;
}
}
return 0;
}