hdu2196--Computer(树形DP练习2)

Computer

Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d
& %I64u

Submit Status

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 

给出电脑之间连接的关系,和相互之间的长度,求每台电脑到最远的一个的距离是多少。

对于一个点i来说,i能到的最远距离可能有两种情况:

1.由i走向i的子节点存在最远长度。(向下)

2.由i走向i的父节点存在最远长度。 (向上)

dp[i][0]记录节点i向下的最长距离,belong[i][0]记录向下最长路径经过的i的子节点。

dp[i][0]记录节点i向下的第二长距离,belong[i][0]记录向下第二长路径经过的i的子节点。

flag[i] = 0代表i的父节点的最长路径不经过i, = 1 代表i的父节点的最长路径经过i

状态转移方程:先由dfs,找出所有点向下的距离,然后由上向下层次遍历

设 i是j的父节点

如果节点j的flag[j] = 0 ,那么它的最远距离应该是dp[j][0] 和 i的最远距离+i到j的距离 中的最大值。

如果节点j的flag[j] = 1 ,那么它的最远距离应该是 dp[j][0] 和 i的非包含j的路径的距离+i到j的距离 中的最大值。

注意:随时更新dp[i][0] dp[i][1]的值。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std ;
struct node{
    int u , v , w ;
    int next ;
}edge[11000];
int head[11000] , cnt ;
int dp[11000][2] , flag[11000] , belong[11000][2];
queue <int> que ;
void add(int u,int v,int w)
{
    edge[cnt].u = u ; edge[cnt].v = v ;
    edge[cnt].w = w ;
    edge[cnt].next = head[u] ;
    head[u] = cnt++ ;
}
void dfs(int u)
{
    if( head[u] == -1 )
        return ;
    int i , v , k1 , k2 ;
    for( i = head[u] ; i != -1 ; i = edge[i].next )
    {
        v = edge[i].v ;
        dfs(v) ;
        if( dp[v][0]+edge[i].w > dp[u][0] )
        {
            dp[u][1] = dp[u][0] ; belong[u][1] = belong[u][0] ;
            dp[u][0] = dp[v][0]+edge[i].w ; belong[u][0] = v ;
        }
        else if( dp[v][0]+edge[i].w > dp[u][1] )
        {
            dp[u][1] = dp[v][0]+edge[i].w ; belong[u][1] = v ;
        }
    }
}
int main()
{
    int n , u , v , w ;
    int i ;
    while( scanf("%d", &n) != EOF )
    {
        memset(flag,0,sizeof(flag)) ;
        memset(dp,0,sizeof(dp)) ;
        memset(head,-1,sizeof(head)) ;
        memset(belong,0,sizeof(belong)) ;
        cnt = 0 ;
        add(0,1,0) ;
        for(i = 2 ; i <= n ; i++)
        {
            scanf("%d %d", &u, &w) ;
            add(u,i,w) ;
        }
        dfs(1) ;
        while( !que.empty() ) que.pop() ;
        que.push(0) ;
        while( !que.empty() )
        {
            u = que.front() ;
            que.pop() ;
            for(i = head[u] ; i != -1 ; i = edge[i].next)
            {
                v = edge[i].v ;
                if( flag[v] )
                {
                    if( dp[v][0] + edge[i].w == dp[u][0] )
                    {
                        if( dp[u][1]+edge[i].w > dp[v][0] )
                        {
                            flag[ belong[v][0] ] = 1;
                            dp[v][1] = dp[v][0] ;
                            dp[v][0] = dp[u][1]+edge[i].w ;
                        }
                        else if( dp[u][1] + edge[i].w > dp[v][1] )
                        {
                            flag[ belong[v][0] ] = 1 ;
                            dp[v][1] = dp[u][1] + edge[i].w ;
                        }
                        else
                        {
                            flag[ belong[v][0] ] = 1 ;
                            flag[ belong[v][1] ] = 1 ;
                        }
                    }
                    else
                    {
                        if( dp[u][0]+edge[i].w > dp[v][0] )
                        {
                            flag[ belong[v][0] ] = 1;
                            dp[v][1] = dp[v][0] ;
                            dp[v][0] = dp[u][0]+edge[i].w ;
                        }
                        else if( dp[u][0] + edge[i].w > dp[v][1] )
                        {
                            flag[ belong[v][0] ] = 1 ;
                            dp[v][1] = dp[u][0] + edge[i].w ;
                        }
                        else
                        {
                            flag[ belong[v][0] ] = 1 ;
                            flag[ belong[v][1] ] = 1 ;
                        }
                    }
                }
                else
                {
                    if( dp[u][0]+edge[i].w > dp[v][0] )
                    {
                        flag[ belong[v][0] ] = 1;
                        dp[v][1] = dp[v][0] ;
                        dp[v][0] = dp[u][0]+edge[i].w ;
                    }
                    else if( dp[u][0] + edge[i].w > dp[v][1] )
                    {
                        flag[ belong[v][0] ] = 1 ;
                        dp[v][1] = dp[u][0] + edge[i].w ;
                    }
                    else
                    {
                        flag[ belong[v][0] ] = 1 ;
                        flag[ belong[v][1] ] = 1 ;
                    }
                }
                que.push(v) ;
            }
        }
        for(i = 1 ; i <= n ; i++)
            printf("%d\n", dp[i][0]) ;
    }
    return 0;
}
时间: 2024-10-14 06:32:09

hdu2196--Computer(树形DP练习2)的相关文章

HDU-2196 Computer (树形DP)

最近在看树形DP,这题应该是树形DP的经典题了,写完以后还是有点感觉的.之后看了discuss可以用树分治来做,以后再试一试. 题目大意 找到带权树上离每个点的最远点.︿( ̄︶ ̄)︿ 题解: 对于每一个点的最远点,就是以这个点为根到所有叶子节点的最长距离.但是如果确定根的话,除了根节点外,只能找到每个节点(度数-1)个子树的最大值,剩下一个子树是该节点当前的父亲节点. 所以当前节点的最远点在当前节点子树的所有叶子节点以及父亲节点的最远点上(当父亲节点的最远点不在当前节点的子树上时), 如果父亲节

HDU 2196 Computer 树形DP经典题

链接:http://acm.hdu.edu.cn/showproblem.php? pid=2196 题意:每一个电脑都用线连接到了还有一台电脑,连接用的线有一定的长度,最后把全部电脑连成了一棵树,问每台电脑和其它电脑的最远距离是多少. 思路:这是一道树形DP的经典题目.须要两次DFS,第一次DFS找到树上全部的节点在不同子树中的最远距离和次远的距离(在递归中进行动态规划就可以),第二次DFS从根向下更新出终于答案.对于每次更新到的节点u,他的最远距离可能是来自u的子树,或者是u的父亲节点的最远

HDU 2196 Computer 树形DP 经典题

给出一棵树,边有权值,求出离每一个节点最远的点的距离 树形DP,经典题 本来这道题是无根树,可以随意选择root, 但是根据输入数据的方式,选择root=1明显可以方便很多. 我们先把边权转化为点权,放在数组cost中 令tree(i)表示以节点i为根的子树 对于节点i,离该节点最远的点要不就是在tree(i)中,要不就是在father(i)上面 令: dp[i][1] : 在子树tree(i)中,离i最远的距离 dp[i][2] : 在子树tree(i)中,离i第二远的距离 (递推的时候需要)

hdu-2169 Computer(树形dp+树的直径)

题目链接: Computer Time Limit: 1000/1000 MS (Java/Others)     Memory Limit: 32768/32768 K (Java/Others) 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 co

HDU 2169 Computer[树形dp]

Computer 时限:1000ms 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 s

hdu2196:树形dp

其实很简单,先计算子树的max,再计算父树的max就OK了: ----------------------------------------------------------------------------------- #include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<vector>using namespace std;#def

[HDU2196]Computer(DP)

传送门 题意 给出一棵树,求离每个节点最远的点的距离 思路 对于我这种菜鸡,真是难啊. 我们能够很简单的求出每个点到以它为根的子树的最远点的距离,dfs 即可. 设 f[i][0] 表示点 i 到以它为根的子树的最远点的距离 f[i][1] 表示点 i 到以它为根的子树的次远点的距离(一会会用到) f[i][2] 表示 除去点 i 的子树后,点 i 到离它最远的点的距离  val 表示边权 那么 f[v][2] 怎么求?(u 表示 v 的父亲) if(f[v][0] + val[i] == f[

HDU2196 Computer(树形DP)

和LightOJ1257一样,之前我用了树分治写了.其实原来这题是道经典的树形DP,感觉这个DP不简单.. dp[0][u]表示以u为根的子树中的结点与u的最远距离 dp[1][u]表示以u为根的子树中的结点与u的次远距离 这两个可以一遍dfs通过儿子结点转移得到.显然dp[0][u]就是u的一个可能的答案,即u往下走的最远距离,还缺一部分就是u往上走的最远距离: dp[2][u]表示u往上走的最远距离 对于这个的转移,分两种情况,是这样的: dp[2][v] = max( dp[0][u]+w

【树形dp小练】HDU1520 HDU2196 HDU1561 HDU3534

[树形dp]就是在树上做的一些dp之类的递推,因为一般需要递归处理,因此平凡情况的处理可能需要理清思路.昨晚开始切了4题,作为入门训练.题目都非常简单,但是似乎做起来都还口以- hdu1520 Anniversary party 给一颗关系树,各点有权值,选一些点出来.任一对直接相连的边连接的点不能同时选择,问选择出的权值和最大为多少. 考虑以u为根的子树可以选择的方法,dp[u]表示选择u时能获得最大收益,dp2[u]表示不选u时能获得的最大收益.则u不选时,为dp2[u]=max{dp[v]

SGU 149. Computer Network( 树形dp )

题目大意:给N个点,求每个点的与其他点距离最大值 很经典的树形dp...很久前就想写来着...看了陈老师的code才会的...mx[x][0], mx[x][1]分别表示x点子树里最长的2个距离, dfs一遍得到. mx[x][2]表示从x的父亲到x的最长路径长度, 也是dfs一遍得到(具体看代码).最后答案就是max(mx[x][0], mx[x][2]). 时间复杂度O(N) ----------------------------------------------------------