HDU 2196-Computer(树形dp)

题意:

给出电脑网络连接树,求每个节点的为起点的最长距离

分析:

这道题开始状态想不出来,放了一段时间,后来注意到例题上有这道题,每个节点的最长距离可由父节点的最长距离,次长距离,和子节点的最长距离(三者取最大)决定。先用一个dfs求出各节点由各子树确定的最长距离,次长距离,再用一个dfs由父节点推各子节点的最长距离。

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <string>
#include <cctype>
#include <complex>
#include <cassert>
#include <utility>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
#define lson l,m,rt<<1
#define pi acos(-1.0)
#define rson m+1,r,rt<<11
#define All 1,N,1
#define read freopen("in.txt", "r", stdin)
#define N 10010
const ll  INFll = 0x3f3f3f3f3f3f3f3fLL;
const int INF= 0x7ffffff;
const int mod =  1000000007;
struct edge{
    int t,d;
};
//p[i]由父节点来的最长距离
//dp[i]由子树来的最长距离
//g[i]由子树来的次长距离
int dp[N],p[N],g[N],n,longest[N];
vector<edge>e[N];
int dfs(int root){
    if(e[root].size()==0)
        return 0;
    if(dp[root])return dp[root];//记忆化搜索
    int tmp;
    for(int i=0;i<e[root].size();++i){
        int son=e[root][i].t;
        int cost=e[root][i].d;
        if(dfs(son)+cost>dp[root]){
            g[root]=dp[root];
            dp[root]=dp[son]+cost;
            tmp=son;
        }
        else if(dp[son]+cost>g[root])g[root]=dp[son]+cost;
    }
    longest[root]=tmp;//把取最长距离的子节点存起来,方便后面由次长距离的更新最长
    return dp[root];
}
void dfs1(int root){
    for(int i=0;i<e[root].size();++i){
        int son=e[root][i].t;
        int cost=e[root][i].d;
        if(son==longest[root])//若在该子节点取得最长距离 ,由父节点的来自父节点的最长距离和来自子树的次长距离更新
            p[son]=max(p[root],g[root])+cost;
        else
            p[son]=max(p[root],dp[root])+cost;//否则,由父节点的来自父节点的最长距离和来自子树的最长距离更新
        dfs1(son);
    }
}
int main()
{
    while(~scanf("%d",&n)){
        edge b;
        int a;
        memset(dp,0,sizeof(dp));
        memset(p,0,sizeof(p));
        memset(g,0,sizeof(g));
        for(int i=1;i<=n;++i){
            e[i].clear();
        }
        for(int i=2;i<=n;++i){
            scanf("%d%d",&a,&b.d);
            b.t=i;
            e[a].push_back(b);
        }
        dfs(1);
        dfs1(1);
        for(int i=1;i<=n;++i){
            printf("%d\n",max(p[i],dp[i]));
        }
    }
return 0;
}

  

时间: 2024-10-21 04:13:16

HDU 2196-Computer(树形dp)的相关文章

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 时限: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

HDU 2196(树形dp

题目:求出一棵树上的所有点到其他点的最长距离. 思路:取一个根节点进行dfs,先求出每个节点到子节点的最长路和次长路(也就是与最长路不同的最长的路,有可能与最长路长度相等),并记录最长路和次长路通过的相邻节点的标号.然后进行第二次dfs,考虑最长路是通过父节点的情况,如果该节点v在父节点的最长路上,那么需要取次长路,否则就取最长路. 第二次dfs的时候最长路的通过节点还是要更新,因为若某个父节点的最长路是朝祖先走的,那么其子节点的最长路一定朝祖先走,且与v是否在父节点向下的最长路上无关. #in

HDU 2196 Computer 经典树形DP

一开始看错题了,后来发现原来是在一颗带权的树上面求出距离每一个点的最长距离,做两次dfs就好,具体的看注释? #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #incl

hdu 1011(树形dp)

Mark.看着吴神博客写的,还未完全懂. 1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #include <set> 8 #include <map> 9 #include <string>

HDU 2196Computer(树形DP)

给你一颗边带权值的树,求树上的每一点距离其最远的一个点的距离 比较典型的题了,主要方法是进行两次DFS,第一次DFS求出每一个点距离它的子树的最远距离和次远距离,然后第二次DFS从父节点传过来另一侧的树上的距离它的最远距离进行一次比较便可得出任意点的最远距离了 之所以需要记录最远和次远是为了辨别父节点的最远距离是否是根据自己得来,如果是的话应该选择父节点的次远距离,保证结果的准确性 1 //#pragma comment(linker,"/STACK:102400000,102400000&qu

树形DP [HDU 2196] Computer

Computer Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3526    Accepted Submission(s): 1788 Problem Description A school bought the first computer some time ago(so this computer's id is 1). D

HDU 2196 树状dp 求树中节点之间的最长距离

Computer Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3749    Accepted Submission(s): 1892 Problem Description A school bought the first computer some time ago(so this computer's id is 1). Du

HDU-2196 Computer (树形DP)

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