求树上任意一点所能到达的最远距离 - 树上dp

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.

InputInput
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.OutputFor 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

题意 : 给你一颗树,以及树上两点之间的距离,求任意一点所能到的最远的距离。

思路分析:

  对于这个问题,我们可以这样去思考,对于一颗树可以很方便的求出 以当前节点为根节点其所能到达的最远距离,但是这样并不能得到所有的节点的答案,其他的节点需要以其再考虑一下当前节点向上走的情况

再考虑 2 这个节点的时候其最优值可能来自 2 这个子树,也可能来自于右侧的这颗红色的树,即向上走

dp[x][0] 表示 x 节点向下走的最大值, dp[x][1]表示 x 节点向下走的次大值, dp[x][2] 表示 x 节点向上走的最大值。

代码示例:

const int maxn = 1e4+5;

int n;
struct node
{
    int to, cost;

    node(int _to=0, int _cost=0):to(_to), cost(_cost){}
};
vector<node>ve[maxn];
int dp[maxn][3];
int p[maxn];

void dfs1(int x, int fa){

    for(int i = 0; i < ve[x].size(); i++){
        int to = ve[x][i].to;
        int cost = ve[x][i].cost;
        if (to == fa) continue;

        dfs1(to, x);
        if (dp[x][0] <= dp[to][0]+cost){
            dp[x][1] = dp[x][0];
            dp[x][0] = dp[to][0]+cost;
            p[x] = to;
        }
        else if (dp[x][1] < dp[to][0]+cost){
            dp[x][1] = dp[to][0]+cost;
        }
    }
}
void dfs2(int x, int fa){

    for(int i = 0; i < ve[x].size(); i++){
        int to = ve[x][i].to;
        int cost = ve[x][i].cost;
        if (to == fa) continue;

        if (to != p[x]){
            dp[to][2] = max(dp[x][0]+cost, dp[x][2]+cost);
        }
        else dp[to][2] = max(dp[x][1]+cost, dp[x][2]+cost);
        dfs2(to, x);

        //printf("++++ %d %d  %d \n", x, to, dp[to][2]);
    }
}

int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    int x, y;
    while(~scanf("%d", &n)){
        for(int i = 1; i <= n; i++) ve[i].clear();
        for(int i = 2; i <= n; i++){
            scanf("%d%d", &x, &y);
            ve[i].push_back(node(x, y));
            ve[x].push_back(node(i, y));
        }
        memset(dp, 0, sizeof(dp));
        dfs1(1, 0);
        dfs2(1, 0);

        for(int i = 1; i <= n; i++) {
            printf("%d\n", max(dp[i][0], dp[i][2]));
        }
    }

    return 0;
}

原文地址:https://www.cnblogs.com/ccut-ry/p/9188796.html

时间: 2024-10-18 19:48:25

求树上任意一点所能到达的最远距离 - 树上dp的相关文章

HDU 2196 求树上所有点能到达的最远距离

其实我不是想做这道题的...只是今天考试考了一道类似的题...然后我挂了... 但是乱搞一下还是有80分....可惜没想到正解啊! 所以今天的考试题是: 巡访 (path.pas/c/cpp) Chanxer终于当上了“中华农民联盟”的盟主,他举目四望,决定四处走走,巡视自己的农土. “中华农民联盟”的成员有个村庄,在“村村通”计划中,村庄们被条道路联通了起来,Chanxer计划从某个村庄出发,访问所有的村庄. 可是Chanxer出行有一个特殊的要求,那就是必须以农车代步,现在我们知道哪些村庄配

HDU 4123(树上任意点到其他点的最远距离,rmq

题目:求出一棵树上任意一点能到的最远距离,然后若干询问,问区间内最大最小距离只差小于q的区间最长有多长. 思路:最远距离通过两次dfs树形dp求得,询问需要先用st表处理一下,然后线性扫.基本是参考kuangbin的. ps:可能是我写挫了..用vector做邻接表是1996ms过了一次,然后就是无限tle....不得不改成手写链表才搞到1500ms...vector感觉不能随便用了啊...... http://www.cnblogs.com/kuangbin/archive/2013/11/0

Uva 10765 点双连通求删任意点后剩下图中的连通分量数

题目挂在wustoj上,不知道什么原因不能粘贴链接.. 第一题题号为1314..这题是智力题...换成7的阶乘就可以了.. 代码如下. #include<cstdio> int main() { printf("...............................................................................................\n"); printf("..#................

关于delphi点击webbrowser中任意一点的问题

关于delphi点击webbrowser中任意一点的问题 有时候我们需要delphi载入webbrowser1打开网页的时候 需要点击某一个点的位置 可能是坐标 可能是按钮 可能是其他的控件应该如何来实现呢? 这里来简单说明一下点击坐标的过程点击过程很明显我们移动鼠标来点击或者发送消息来点击移动鼠标点击的比较常见 这里详细说明一下发送消息来点击的办法发送消息来点击的思路是sendmessage()发送消息来实现的导入句柄 点击的就可以了.但是这里的句柄(webbrowser的句柄)其实是不好找的

HDU 2196 Computer(求树上每个节点到其它点的最远距离)

解题思路: 求出树的直径的两个端点,则树上每个节点到其他点的最远距离一定是到这两个端点的距离中最长的那一个. #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath> #include <vector> #include <queue> #define LL long long using nam

echarts 点击方法总结,点任意一点获取点击数据,举例说明:在多图联动中点击绘制标线

关于点击(包括左击,双击,右击等)echarts图形任意一点,获取相关的图形数据,尤其是多图,我想部分人遇到这个问题一直很头大.下面我用举例说明,如何在多图联动基础上,我们点击任意一个图上任意一点,在点击处绘制一条标注线.多图联动的用法,我就不详细解释,不明白或者感兴趣的同学可以看我上一篇:http://www.cnblogs.com/mobeisanghai/p/7683158.html ,虽然最近很忙,很久没更新,但是基本清晰.关于引入样式和js,以及初始元素如下: <script src=

从1到非负整数n中1出现的次数 求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数? 为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次, 但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化, 可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。

/*从1到非负整数n中1出现的次数求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1.10.11.12.13因此共出现6次,但是对于后面问题他就没辙了.ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数). */ import java.util.*; public class Class36 { public int NumberOf1Between1A

Dijkstra算法(求一点到任意一点的最短距离)

思路:先找出最短的一个点,也就是起点,从起点出发,找最短的边,同时标记起点为true(代表已经访问过),访问过的点就不用再访问了,依次下去,保证每一次找到的边都是最短的边 到最后没有边可以更新了就代表结束 看代码 #include<iostream> #include<cstdio> #include<cstring> #include<stdio.h> #include<string.h> #include<cmath> #incl

HDU 5001 Walk 求从任意点出发任意走不经过某个点的概率 概率dp 2014 ACM/ICPC Asia Regional Anshan Online

题意: 给定n个点m条边的无向图 问: 从任意点出发任意走d步,从不经过某个点的概率 dp[i][j]表示从不经过i点的前提下,走了d步到达j点的概率. #include <iostream> #include <cstdio> #include <string.h> #include <queue> #include <vector> #include <algorithm> #include <set> using n