http://acm.hdu.edu.cn/showproblem.php?pid=2196
https://www.acwing.com/problem/content/description/327/
题意:
一所学校前一段时间买了第一台计算机(所以这台计算机的ID是1)。
近年来,学校又购买了N-1台新计算机。
每台新计算机都与之前买进的计算机中的一台建立连接。
现在请你求出第i台计算机到距离其最远的计算机的电缆长度。
输入格式
输入包含多测试数据。
每组测试数据第一行包含整数N。
接下来N-1行,每行包含两个整数,第 i 行的第一个整数表示第 i 台电脑买入时连接的电脑编号,第二个整数表示这次连接花费的电缆长度。
输出格式
每组测试数据输出N行。
第 i 行输出第 i 台电脑的 Si。
数据范围
1≤N≤10000,
电缆总长度不超过10^9
假如这些电脑组成了一棵树,对于一个节点,其最远的节点:
1.经过父亲节点
2.不经过父亲节点
对于第二点很好解决,我们用dp[i]表示节点i到其最长叶子节点的距离,然后来一次dp
对于第一点,首先我们需要判断这个节点是否为父亲节点到父亲节点的最长叶子节点之间需要经过的点
假如不是那好说,就是父亲节点到父亲节点的最长叶子节点的距离+这个节点和父亲节点的距离
假如是,那么则需要父亲节点到父亲节点的次长叶子节点的距离+这个节点和父亲节点的距离
因此我们需要知道父亲节点到其叶子节点的最长和次长距离就可以了
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1e4 + 7;
int Head[maxn], Nxt[maxn << 1], Val[maxn << 1], To[maxn << 1];
// dp[i]表示节点i到其最长叶子节点的距离
int dp[maxn], ans[maxn];
int n, tot;
void init() {
memset(Head, 0, (n + 2) * sizeof(Head[0]));
tot = 0;
//memset(dp, 0, (n + 2) * sizeof(dp[0]));
}
void add_edge(int fro, int to, int val) {
Nxt[++tot] = Head[fro]; Head[fro] = tot;
To[tot] = to; Val[tot] = val;
}
//获得最长儿子数组
int dfs1(int now,int fat) {
dp[now] = 0;
for (int i = Head[now]; i; i = Nxt[i]) {
int &to = To[i], &val = Val[i];
if (to == fat)
continue;
dp[now] = max(dp[now], val + dfs1(to, now));
}
return dp[now];
}
//hav:经过父亲节点的最长距离
void dfs2(int now,int fat,int hav) {
//mx1:到叶子节点的最长距离 mx2:到叶子节点的次长距离
//mx_id:保存mx1的id
int mx1, mx2, mx1_id;
mx1 = mx2 = 0;
for (int i = Head[now]; i; i = Nxt[i]) {
int &to = To[i], &val = Val[i];
if (to == fat)
continue;
if (mx1 <= val + dp[to]) {
mx1_id = to;
mx2 = mx1;
mx1 = val + dp[to];
}
else if (mx2 < val + dp[to])
mx2 = val + dp[to];
}
ans[now] = max(mx1, hav);
for (int i = Head[now]; i; i = Nxt[i]) {
int &to = To[i], &val = Val[i];
if (to == fat)
continue;
if (to == mx1_id)
dfs2(to, now, val + max(hav, mx2));
else
dfs2(to, now, val + max(hav, mx1));
}
}
int main() {
while (cin >> n) {
init();
int to, val;
for (int i = 2; i <= n; i++) {
scanf("%d %d", &to, &val);
add_edge(i, to, val);
add_edge(to, i, val);
}
dfs1(1, 0);
dfs2(1, 0, 0);
for (int i = 1; i <= n; i++)
printf("%d\n", ans[i]);
}
return 0;
}