Computer HDU 2196 (树形dp)

Computer HDU-2196

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.

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

个人理解

我们处理一个根到这棵树所有节点的最长路径容易处理,然后拿到这个题我第一反应就是:那就让每个点作为根跑一边最基本自底向上的树形dp不就可以了,不出意外,TLE了。然后就猜这个题肯定是按照一个点为根跑一遍树形dp,然后再进行一系列的操作,得出来所有的为根的最远距离。
我们想哈,当你跑第一遍树形dp时候,从父节点走到这个子节点的时候,会继续求出以这个子节点为根的子树的最远距离,那么他就只能往他的子节点方向跑了。那如果离这个子节点最远的那个点在他的父节点方向上怎么办呢,我们可以让他往他的父节点跑就可以了,但是如果再以他的父节点为根跑下一层dfs的时候又会跑回这个点。
所以我们用f[i]和g[i]分别记录,第i个节点往儿子节点方向和往他父亲节点方向的最远距离,跑两次dfs,分别处理这两个数组的值。递推关系如下:
f [ u ] = m a x ( f [ v ] , w ( u , v ) ) f[u] = max(f[v],w(u,v)) f[u]=max(f[v],w(u,v))
g [ u ] = w ( u , p [ u ] ) + m a x ( g [ p [ u ] ] , f [ v ] + w ( p [ u ] , v ) ) ( p [ u ] 是 u 的 父 亲 , v 是 p [ u ] 的 儿 子 , v ≠ u ) g[u] = w(u,p[u])+max(g[p[u]],f[v]+w(p[u],v))(p[u]是u的父亲,v是p[u]的儿子,v \neq u) g[u]=w(u,p[u])+max(g[p[u]],f[v]+w(p[u],v))(p[u]uvp[u],v̸=u)

代码

#include <bits/stdc++.h>
using namespace std;
inline int read() {int x=0;char p=getchar();while(p<'0'||p>'9')p=getchar();while(p>='0'&&p<='9')x=x*10+p-'0',p=getchar();return x;}
const int maxn = 10010;

struct node{
	int to;
	int w;
	int next;
}edge[maxn<<1];
int cnt,head[maxn];
int f[maxn],g[maxn],p[maxn];
int n;

void init(){
	cnt = 0;
	memset(head,-1,sizeof(head));
}

void add(int u,int v,int w){
	edge[cnt].to = v;
	edge[cnt].w = w;
	edge[cnt].next = head[u];
	head[u] = cnt++;
}

int dfs(int cur,int pre){
    f[cur] = 0;
    for(int i = head[cur];i!=-1;i = edge[i].next){
        if(edge[i].to != pre){
            p[edge[i].to] = cur;
            f[cur] = max(f[cur],dfs(edge[i].to,cur)+edge[i].w);
        }
    }
    return f[cur];
}

void dfs1(int cur,int pre){
    int t = 0;
    g[cur] = g[pre];
    for(int i = head[pre];i!=-1;i = edge[i].next){
        int v = edge[i].to;
        if(v == p[pre]) continue;
        if(v == cur){
        	t = edge[i].w;
        }else{
            g[cur] = max(g[cur],f[v]+edge[i].w);
		}
    }
    g[cur]+=t;
    for(int i = head[cur];i!=-1;i = edge[i].next){
        if(edge[i].to!=pre){
            dfs1(edge[i].to,cur);
        }
    }
}

int main(){
	while(~scanf("%d",&n)){
		init();
		for(int u = 2;u<=n;u++){
			int v,w;
			v = read();
			w = read();
			add(u,v,w);
			add(v,u,w);
		}
        dfs(1,0);dfs1(1,0);
        for(int i = 1;i<=n;i++){
            printf("%d\n",max(f[i],g[i]));
        }
	} 
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值