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第二远的距离 (递推的时候需要)

dp[i][0] : 在树tree(root)-tree(i)中,离i最远的距离

son[i] : 在子树tree(i)中,离i最远的点是在tree(son[i])中,即最远路径经过节点son[i]

则对于每一个i,离i最远的距离=max(dp[i][0],dp[i][1])

流程:

0.链式前向星建树

1.dfs1,确定dp[i][1]

2.dfs2,确定dp[i][2]

dfs1和dfs2都很简单

3.dfs3,递推确定dp[i][0]

  1 #include<cstdio>
  2 #include<cstring>
  3
  4 using namespace std;
  5
  6 const int maxn=10000+5;
  7 const int inf=0x3f3f3f3f;
  8
  9 inline int max(int a,int b)
 10 {
 11     return a>b?a:b;
 12 }
 13
 14 struct Edge
 15 {
 16     int to,next;
 17 };
 18 Edge edge[maxn];
 19 int head[maxn];
 20 int tot;
 21 int cost[maxn];
 22 int son[maxn];
 23 int dp[maxn][3];
 24
 25 void init()
 26 {
 27     memset(head,-1,sizeof head);
 28     tot=0;
 29     memset(dp,0,sizeof dp);
 30     memset(son,-1,sizeof son);
 31 }
 32
 33 void addedge(int u,int v)
 34 {
 35     edge[tot].to=v;
 36     edge[tot].next=head[u];
 37     head[u]=tot++;
 38 }
 39
 40 void solve(int n);
 41 void dfs1(int u,int pre);
 42 void dfs2(int u,int pre);
 43 void dfs3(int u,int pre);
 44
 45 int main()
 46 {
 47     int n;
 48     while(~scanf("%d",&n))
 49     {
 50         init();
 51         cost[1]=0;
 52         for(int i=2;i<=n;i++)
 53         {
 54             int u;
 55             scanf("%d %d",&u,&cost[i]);
 56             addedge(u,i);
 57         }
 58         solve(n);
 59     }
 60     return 0;
 61 }
 62
 63 void solve(int n)
 64 {
 65     dfs1(1,-1);
 66     dfs2(1,-1);
 67     dp[1][0]=0;
 68     dfs3(1,-1);
 69
 70     for(int i=1;i<=n;i++)
 71     {
 72         printf("%d\n",max(dp[i][0],dp[i][1]));
 73     }
 74     return ;
 75 }
 76
 77 void dfs1(int u,int pre)
 78 {
 79     for(int i=head[u];~i;i=edge[i].next)
 80     {
 81         int v=edge[i].to;
 82         dfs1(v,u);
 83         if(dp[v][1]+cost[v]>dp[u][1])
 84         {
 85             dp[u][1]=dp[v][1]+cost[v];
 86             son[u]=v;
 87         }
 88     }
 89 }
 90
 91 void dfs2(int u,int pre)
 92 {
 93     for(int i=head[u];~i;i=edge[i].next)
 94     {
 95         int v=edge[i].to;
 96         dfs2(v,u);
 97         if(v==son[u])
 98             continue;
 99         if(dp[v][1]+cost[v]>dp[u][2])
100             dp[u][2]=dp[v][1]+cost[v];
101     }
102 }
103
104 void dfs3(int u,int pre)
105 {
106     for(int i=head[u];~i;i=edge[i].next)
107     {
108         int v=edge[i].to;
109         if(v==son[u])
110         {
111             dp[v][0]=max(dp[u][0],dp[u][2])+cost[v];
112         }
113         else
114         {
115             dp[v][0]=max(dp[u][0],dp[u][1])+cost[v];
116         }
117         dfs3(v,u);
118     }
119 }

时间: 2024-12-13 15:32:28

HDU 2196 Computer 树形DP 经典题的相关文章

HDU 2196 Computer 树形DP经典题

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

树形DP经典题

题目传送门 题意: 给出一棵树,求离每个节点最远的点的距离 思路: 把无根树转化成有根树分析, 对于上面那棵树,要求距结点2的最长距离,那么,就需要知道以2为顶点的子树(蓝色圈起的部分,我们叫它Tree(2)),距顶点2的最远距离L1 还有知道2的父节点1为根节点的树Tree(1)-Tree(2)部分(即红色圈起部分),距离结点1的最长距离+dist(1,2) = L2,那么最终距离结点2最远的距离就是max{L1,L2} f[i][0],表示顶点为i的子树的,距顶点i的最长距离 f[i][1]

POJ 1155 TELE 背包型树形DP 经典题

由电视台,中转站,和用户的电视组成的体系刚好是一棵树 n个节点,编号分别为1~n,1是电视台中心,2~n-m是中转站,n-m+1~n是用户,1为root 现在节点1准备转播一场比赛,已知从一个节点传送数据到达另一个节点,电视台需要一定的费用 若可以传送数据到达用户的节点n-m+1~n,这些用户各自愿意支付一定的费用给电视台 现在电视台希望在不亏本的情况下为尽量多的用户转播比赛 输出最多可以为多少用户转播比赛 背包类型的树形DP第一题 dp[i][j]表示以节点i为根的子树有j个用户获得转播,电视

POJ 1947 Rebuilding Roads (树形dp 经典题)

Rebuilding Roads Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 9499   Accepted: 4317 Description The cows have reconstructed Farmer John's farm, with its N barns (1 <= N <= 150, number 1..N) after the terrible earthquake last May. The

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 - 1003 Max Sum(DP经典题2)

题意:给出一串数,求最大和的字串和起始终点位置. 与导弹问题大同小异,有状态转移方程就很好做了. 状态转移方程:d[i]=(d[i-1]+a[i]>a[i])?d[i-1]+a[i]:a[i]; 1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 5 const int maxn=100000+10; 6 7 int dp[maxn],num[maxn]; 8 9 int main(){ 10

POJ 2486 Apple Tree (树形dp 经典题)

Apple Tree Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7784   Accepted: 2603 Description Wshxzt is a lovely girl. She likes apple very much. One day HX takes her to an apple tree. There are N nodes in the tree. Each node has an amoun

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