码迷,mamicode.com
首页 > 其他好文 > 详细

树形dp专辑

时间:2015-04-15 19:24:06      阅读:175      评论:0      收藏:0      [点我收藏+]

标签:

hdu 2196 http://acm.hdu.edu.cn/showproblem.php?pid=2196

input

5//5个结点

1 1//表示结点2到结点1有一条权值为1的边

2 1//表示结点3到结点2有一条权值为1的边

3 1

1 1

要我们求从任意结点出发的最长路径。

思路:一棵树上从某个结点出发的最长路径,肯定是①从该结点出发经由子树到大叶子结点。②从该结点出发经由父结点,然后到大叶子结点。      这两者中的最大者

  ①可以用一遍dfs求出任意结点到叶子结点的最大值。

  ②也是用一遍dfs求出任意结点经由父结点到达叶子结点的最大值

  最后两者取max即可

技术分享
 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4 #include <algorithm>
 5 #include <iostream>
 6 #include <queue>
 7 #include <stack>
 8 #include <vector>
 9 #include <map>
10 #include <set>
11 #include <string>
12 #include <math.h>
13 using namespace std;
14 typedef long long LL;                   
15 const int INF = 1<<30;
16 const int N = 10000 + 10;
17 struct computer
18 {
19     int v,len;
20 };
21 vector<computer> g[N];
22 int maxn[N],smax[N];
23 int maxnId[N],smaxId[N];
24 int up[N];//up[]记录的是从父亲结点转到根结点的最大值
25 //dfs生成一棵树,然后求的每个结点到叶子结点的最大值和次大值, 最大值和次大值不在一个分支上面
26 void dfs1(int u, int fa)
27 {
28     maxn[u] = smax[u] = 0;
29     for(int i=0; i<g[u].size(); ++i)
30     {
31         int v = g[u][i].v;
32         if(v!=fa)//如果u的一个分支v用来更新最长路,那么就不会更新次长路,所以maxn[u]是u最长的一个分支,smax[v]是v次长的一个分支
33             //因为是树,所以分支是没有交点的。
34             //感觉求出来的次长路不是次长路
35         {
36             dfs1(v,u);
37             if(maxn[u] < maxn[v] + g[u][i].len)//最长
38             {
39                 smax[u] = maxn[u];
40                 maxn[u] = maxn[v] + g[u][i].len;
41                 smaxId[u] = maxnId[u];
42                 maxnId[u] = v;//结点u的最长路是经过结点v这个分支然后到达叶子结点
43             }
44             else if(smax[u] < maxn[v] + g[u][i].len)//次长
45             {
46                 smax[u] = maxn[v] + g[u][i].len;
47                 smaxId[u] = v;
48             }
49         }
50     }
51 }
52 
53 void dfs2(int u, int fa)
54 {
55     for(int i=0; i<g[u].size();++i)
56     {
57         int v = g[u][i].v;
58         if(v==fa) continue;
59         if(v!=maxnId[u])//如果父节点到根结点的最大值不是从v这个分支接入的,那么v从到结点再到根结点的最大值为
60         {
61             up[v] = max(up[u],maxn[u])+g[u][i].len;//v到父亲,然后父亲到叶子结点的最大值或者父亲经由父亲的父亲到达叶子结点的最大值
62         }
63         else//如果父节点到根结点的最大是从v这个分支接入的,那么fmax[u]+g[u][i].len就会有重叠的部分,所以只能用smax[u]+g[u][i].len
64         {
65             up[v] = max(up[u],smax[u]) + g[u][i].len;
66         }
67         dfs2(v,u);
68     }
69 }
70 int main()
71 {
72     int n,i,x,len;
73     computer tmp;
74     while(scanf("%d",&n)!=EOF)
75     {
76         
77         for(i=1; i<=n; ++i)
78             g[i].clear();
79         for(i=2; i<=n; ++i)
80         {
81             scanf("%d%d",&x,&len);
82             tmp.v = x;
83             tmp.len = len;
84             g[i].push_back(tmp);
85             tmp.v = i;
86             g[x].push_back(tmp);
87         }
88         dfs1(1,-1);//设1为根结点,然后dfs,生成dfs树
89         up[1] = 0;//更结点没有父亲结点,所以经由父亲结点到达根结点的最大值为0
90         dfs2(1,-1);
91         
92         for(i=1; i<=n; ++i)
93             printf("%d\n",max(maxn[i],up[i]));
94     }
95     return 0;
96 }
View Code

 

树形dp专辑

标签:

原文地址:http://www.cnblogs.com/justPassBy/p/4429141.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!