Computer
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 31201 Accepted Submission(s): 3989
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.
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
题目大意:
给你一棵树,每条边都有长度,求任意一个点可以到达的最远距离
输入:
5 //一共有五个点
1 1 //第1条边为1->2,距离为1
2 1 //第2条边为2->3,距离为1
3 1 //第3条边为3->4,距离为1
1 1 //第4条边为1->5,距离为1
思路:
这是我做的树形dp的第二道题,说实话看了很久才弄懂,话不多说了来看一下做法吧
1.
首先思考下,一颗树的最远距离,是不是有两种可能,这里借用了大佬的一个图
如图,拿结点2来说,他的最远距离有两种可能,(1)他到叶子结点的最远距离L1 (2)(他的父节点(即结点1)到叶子结点的最远距离+父节点与它的距离)L2 那么他的最远距离就是max(L1,L2);
上面那里可能说的不是很清楚,可以这样理解:为方便叙述,将当前结点称为i其父亲结点为j;
L1为以i为根的子树中i的最远距离
L2为以j为根的子树(这个子树不能含有i)中j的最远距离+j到i的距离
2.
那么如何求L1与L2呢
L1:
L1好说,dfs一遍树,找到每个结点到叶子结点的最远距离即可,我们这里记为dp[i][0]表示i节点到叶子结点的最远距离;
我们这里再保存一个dp[i][1]表示i结点到叶子结点的次远距离,至于它有什么作用,我们稍后再说;
L2:
这时我们用dp[i][2]来表示L2,这时dp[j][1]就派上用场了,因为dp[j][0]保存的是j到叶子结点的最远距离,此时我们不能直接用,因为这个最远距离可能经过了i,我们先判断是否经过i,如果没有经过那么dp[i][2]=dp[j][2]+len(j->i),若经过了那么dp[i][2]=dp[j][1]+len(j->i);
void dfs2(int u)
{
for(int i=0;i<xs[u].size();i++)
{
int to=xs[u][i].to;
int val=xs[u][i].val;
dp[to][2]=max(dp[u][2],dp[to][0]+val==dp[u][0]?dp[u][1]:dp[u][0])+val;
dfs2(to);
//判断从父节点到叶子结点的最远距离是否经过当前点,若经过则取父节点的次大距离
//最后加上父节点到当前点的距离即为当前点从父节点过来的最大距离
}
}
最后比较dp[i][0]与dp[i][2]即可;
PS:还是感觉没说清楚....
代码如下
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <string>
using namespace std;
const int maxn = 10010;
int dp[maxn][4]; //dp[i][0]--i到叶子节点的最远距离 dp[i][1]--第二远距离 dp[i][2]从父节点到叶子结点的最大距离(不经过当前点
typedef struct{
int to; //到下一个点
int val; //到下一个点的距离
}NODE;
vector<NODE>xs[maxn];
void dfs1(int u)
{
int max1=0; //最大距离
int max2=0; //第二大距离
for(int i=0;i<xs[u].size();i++)
{
NODE next=xs[u][i];
dfs1(next.to); //DFS下一个点
int nowmax=dp[next.to][0]+next.val; //当前所保存的最大距离
if(max1<=nowmax) //当前最大距离大于最大距离
{
max2=max1; //更新最大距离与次大距离
max1=nowmax;
}
else if(max2<nowmax) //当前最大距离大于次大距离但是小于最大距离
{
max2=nowmax; //更新次大距离
}
}
dp[u][0]=max1; //更新DP数组
dp[u][1]=max2;
}
void dfs2(int u)
{
for(int i=0;i<xs[u].size();i++)
{
int to=xs[u][i].to;
int val=xs[u][i].val;
dp[to][2]=max(dp[u][2],dp[to][0]+val==dp[u][0]?dp[u][1]:dp[u][0])+val;
dfs2(to);
//判断从父节点到叶子结点的最远距离是否经过当前点,若经过则取父节点的次大距离
//最后加上父节点到当前点的距离即为当前点从父节点过来的最大距离
}
}
int main()
{
int N;
scanf("%d",&N);
for(int i=2;i<=N;i++)
{
int to,val;
scanf("%d %d",&to,&val);
NODE x;
x.to=i;
x.val=val;
xs[to].push_back(x);
}
memset(dp,0,sizeof(dp));
dfs1(1);
// cout<<"ok1"<<endl;
dfs2(1);
// cout<<"ok2"<<endl;
for(int i=1;i<=N;i++)
{
printf("%d\n",max(dp[i][0],dp[i][2]));
}
for(int i=1;i<=N;i++)
xs[i].clear();
}