computer(树形dp || 树的直径)

时间:2023-03-10 03:50:42
computer(树形dp || 树的直径)

Computer

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 38417    Accepted Submission(s): 6957

Problem Description
A school bought the first computer some time ago(so this computer's id is 1). During the recent years the school bought N-1 new computers. Each new computer was connected to one of settled earlier. Managers of school are anxious about slow functioning of the net and want to know the maximum distance Si for which i-th computer needs to send signal (i.e. length of cable to the most distant computer). You need to provide this information. 
computer(树形dp || 树的直径)

Hint: the example input is corresponding to this graph. And from the graph, you can see that the computer 4 is farthest one from 1, so S1 = 3. Computer 4 and 5 are the farthest ones from 2, so S2 = 2. Computer 5 is the farthest one from 3, so S3 = 3. we also get S4 = 4, S5 = 4.

Input
Input file contains multiple test cases.In each case there is natural number N (N<=10000) in the first line, followed by (N-1) lines with descriptions of computers. i-th line contains two natural numbers - number of computer, to which i-th computer is connected and length of cable used for connection. Total length of cable does not exceed 10^9. Numbers in lines of input are separated by a space.
Output
For each case output N lines. i-th line must contain number Si for i-th computer (1<=i<=N).
Sample Input
5
1 1
2 1
3 1
1 1
Sample Output
3
2
3
4
4
Author
scnu
Recommend
lcy
 /*************************************************************************
> File Name: computer.cpp
> Author: CruelKing
> Mail: 2016586625@qq.com
> Created Time: 2019年09月23日 星期一 14时08分02秒
我的思路:先求出直径的两个端点,接着求出所有顶点到两个端点的距离,取其中最大的即是答案.
第二种思路:一个顶点距离其他顶点的最远距离要么经过儿子结点,要么经过父亲结点,那么我们就都求出来取其大就可以了.
需要注意的是,如果说一个说父亲的最远距离经过儿子的最远距离的话,儿子需要换一条路次短路.
************************************************************************/ #include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = + ;
struct Edge {
int to, cost, next;
} edge[maxn << ]; int n, ans; int head[maxn], tot;
//int dp[maxn];//某棵树子树的大小 # TODO:这是用树的直径的时候保存的状态 int dp[maxn][];//用dp[i][0]表示i的子树的最远距离,dp[i][1]表示i的子树的次远距离
//dp[i][2]表示i的祖先的最远距离,所以答案取max(dp[i][0], dp[i][2]) void init() {
memset(head, -, sizeof head);
tot = ;
} void addedge(int u, int v, int w) {
edge[tot].to = v; edge[tot].next = head[u]; edge[tot].cost = w; head[u] = tot ++;
edge[tot].to = u; edge[tot].next = head[v]; edge[tot].cost = w; head[v] = tot ++;
} /*
void dfs(int u, int pre) {
//TODO:求解树的直径
//本题没用到该函数
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if(v == pre) continue;
dfs(v, u);
if(ans < dp[u] + dp[v] + edge[i].cost) {
ans = dp[u] + dp[v] + edge[i].cost;
}
if(dp[v] + edge[i].cost > dp[u]) {
dp[u] = edge[i].cost + dp[v];
}
}
}
*/ /*
int d, M;
int A, B; int dist[maxn]; void dfs(int u, int pre, bool flag) {
//TODO:递归寻找树的直径的端点
if(d > M) {
M = d;
if(flag)
A = u;
else
B = u;
}
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if(pre == v) continue;
d += edge[i].cost;
if(!flag) dist[v] = d;
dfs(v, u, flag);
d -= edge[i].cost;
}
} void dfs1(int u, int pre) {
//TODO;寻找每个点距离两个端点的最大值
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if(pre == v) continue;
d += edge[i].cost;
dist[v] = max(d, dist[v]);
dfs1(v, u);
d -= edge[i].cost;
}
}
*/ void dfs(int u, int pre) {
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if(v == pre) continue;
dfs(v, u);
int temp = ;
if(dp[u][] <= dp[v][] + edge[i].cost) {
dp[u][] = dp[u][];
dp[u][] = dp[v][] + edge[i].cost;
} else if(dp[u][] < dp[v][] + edge[i].cost) {
dp[u][] = edge[i].cost + dp[v][];
}
}
// printf("%d %d %d\n", u, dp[u][0], dp[u][1]);
} void dfs1(int u, int pre) {
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if(v == pre) continue;
dp[v][] = max(dp[u][], dp[v][] + edge[i].cost == dp[u][] ? dp[u][] : dp[u][]) + edge[i].cost;
dfs1(v, u);
}
} int main() {
int v, w;
while(~scanf("%d", &n)) {
ans = ;
init();
memset(dp, , sizeof dp);
for(int i = ; i <= n; i ++) {
scanf("%d %d", &v, &w);
addedge(i, v, w);
}
/*TODO:利用树的直径求解本题
memset(dist, 0, sizeof dist);
d = M = 0;
dfs(1, -1, true);
M = 0;
dfs(A, -1, false);
// for(int i = 1; i <= n; i ++) {
// printf("%d\n", dist[i]);
// }
dfs1(B, -1);
for(int i = 1; i <= n; i ++) {
printf("%d\n", dist[i]);
}
*/
//TODO:利用树形dp求解本题
dfs(, -);
dfs1(, -);
for(int i = ; i <= n; i ++) {
printf("%d\n", max(dp[i][], dp[i][]));
}
}
return ;
}