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

题意:找出树中每个节点到其它点的最远距离。

题解:

  首先这是一棵树,对于节点v来说,它到达其它点的最远距离可以走两个方向,一个是向它的子节点走,不妨称作正向走;一个是向它的父节点方向,不妨称作反向走。也就是说节点v能到达的最远距离是max{正向走的最远距离,反向走的最远距离}。所以可以先dfs一次求出每个节点能正向走的最大距离。显然反向走一定会经过父节点,这时就会出现两种情况:1.父节点u正向走的最远距离经过子节点v。2.父节点u走的最远距离不经过子节点v。当经过子节点v时,显然要算v反向走的最远距离时不能走u的正向最远的那条经过自己的路径,而u的正向第二远的路径将是最优的选择。可以想想看,v反向最远当然是由u的正向最远转移过来的,这个正向最远经不经过v很关键。因此正向dfs时还要记录一个第二最远的距离。

  设dp[][3],dp[v][0]表示v正向走的最远距离,dp[v][1]表示v正向走的第二最远距离,dp[v][2]表示v反向走的最远距离。

  那么答案显然是:ans=max{dp[v][0],dp[v][2]}。

  其中:当u最远不经过v时:dp[v][2]=max{dp[u][2],dp[u][0]}+cost;

    当u最远经过v时:dp[v][2]=max{dp[u][2],dp[u][1]}+cost;

  我之前有个非常疑惑的地方就是为什么dp[v][2]的转移还要有dp[u][2]?我直接根据u经不经过v分两种情况不就是dp[v][2]了吗,怎么还要跟dp[u][2]+cost之间取个最大值?后来想想才明白,其实这也是个状态转移啊!dp[u][2]表示u反向走的最远距离,而dp[u][0],dp[u][1]都是正向走的距离,当由u推v的时候当然要从u的正向和反向之间取个最大值了!

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXN=;
struct Node{
int to,cost;
};
vector<Node> tree[MAXN];
int dp[MAXN][];
int N; void init()
{
memset(dp,,sizeof(dp));
for(int i=;i<=N;i++)
tree[i].clear();
} void dfs1(int u,int fa)
{
int FirstMax=,SecondMax=;
for(int i=;i<tree[u].size();i++){
int v=tree[u][i].to;
int c=tree[u][i].cost;
if(v==fa) continue;
dfs1(v,u);
if(dp[v][]+c>FirstMax){
SecondMax=FirstMax;
FirstMax=dp[v][]+c;
}else if(dp[v][]+c>SecondMax)
SecondMax=dp[v][]+c;
}
dp[u][]=FirstMax;
dp[u][]=SecondMax;
} void dfs2(int u,int fa)
{
int t;
for(int i=;i<tree[u].size();i++){
int v=tree[u][i].to;
int c=tree[u][i].cost;
if(v==fa) continue;
if(dp[u][]==dp[v][]+c)
t=dp[u][];
else t=dp[u][];
dp[v][]=max(dp[u][],t)+c;
dfs2(v,u);
}
} int main()
{
while(scanf("%d",&N)==)
{
init();
int a,b;
Node n1;
for(int i=;i<=N;i++){
scanf("%d%d",&a,&b);
n1.to=a,n1.cost=b;
tree[i].push_back(n1);
n1.to=i;
tree[a].push_back(n1);
}
dfs1(,);
dfs2(,);
for(int i=;i<=N;i++)
printf("%d\n",max(dp[i][],dp[i][]));
}
return ;
}

hdu 2196【树形dp】的更多相关文章

  1. HDU 2196树形DP(2个方向)

    HDU 2196 [题目链接]HDU 2196 [题目类型]树形DP(2个方向) &题意: 题意是求树中每个点到所有叶子节点的距离的最大值是多少. &题解: 2次dfs,先把子树的最大 ...

  2. HDU 2196 树形DP Computer

    题目链接:  HDU 2196 Computer 分析:   先从任意一点开始, 求出它到其它点的最大距离, 然后以该点为中心更新它的邻点, 再用被更新的点去更新邻点......依此递推 ! 代码: ...

  3. hdu 2196 树形dp

    思路:先求以1为根时,每个节点到子节点的最大长度.然后再次从1进入进行更新. #include<iostream> #include<cstring> #include< ...

  4. hdu 4123 树形DP+RMQ

    http://acm.hdu.edu.cn/showproblem.php? pid=4123 Problem Description Bob wants to hold a race to enco ...

  5. HDU 1520 树形dp裸题

    1.HDU 1520  Anniversary party 2.总结:第一道树形dp,有点纠结 题意:公司聚会,员工与直接上司不能同时来,求最大权值和 #include<iostream> ...

  6. HDU 1561 树形DP入门

    The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  7. HDU 1520 树形DP入门

    HDU 1520 [题目链接]HDU 1520 [题目类型]树形DP &题意: 某公司要举办一次晚会,但是为了使得晚会的气氛更加活跃,每个参加晚会的人都不希望在晚会中见到他的直接上司,现在已知 ...

  8. codevs 1380/HDU 1520 树形dp

    1380 没有上司的舞会 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 回到问题 题目描述 Description Ural大学有N个职员 ...

  9. HDU 5834 [树形dp]

    /* 题意:n个点组成的树,点和边都有权值,当第一次访问某个点的时候获得利益为点的权值 每次经过一条边,丢失利益为边的权值.问从第i个点出发,获得的利益最大是多少. 输入: 测试样例组数T n n个数 ...

  10. hdu 4267 树形DP

    思路:先dfs一下,找出1,n间的路径长度和价值,回溯时将该路径长度和价值清零.那么对剩下的图就可以直接树形dp求解了. #include<iostream> #include<al ...

随机推荐

  1. Opencv中的阈值函数

    OpenCV基础——threshold函数的使用 图像的二值化就是将图像上的像素点的灰度值设置为0或255,这样将使整个图像呈现出明显的黑白效果. 参数原型 参数说明 src:源图像,可以为8位的灰度 ...

  2. FileReader详解

    一.兼容性 从上图中可以看出IE7.8.9都不支持FileReader对象 二.作用 使用支持FileReader浏览器的用户可以通过一个file input选择一个图像文件将图片显示在页面中,而不用 ...

  3. 实现一个函数clone,使JavaScript中的5种主要的数据类型(包括Number、String、Object、Array、Boolean)进行值复制

    实现一个函数clone,可以对JavaScript中的5种主要的数据类型(包括Number.String.Object.Array.Boolean)进行值复制. 1 /** 对象克隆 2 * 支持基本 ...

  4. DLX

    #include <iostream> #include <cstdlib> #include <cstring> #include <queue> # ...

  5. liunx定时删除文件(产生的日志.........)

    linux是一个很能自动产生文件的系统,日志.邮件.备份等.虽然现在硬盘廉价,我们可以有很多硬盘空间供这些文件浪费,让系统定时清理一些不需要的文件很有一种爽快的事情.不用你去每天惦记着是否需要清理日志 ...

  6. R330 打印机连供墨水红灯常量处理

    墨水灯红灯常量,表示墨盒没墨水 1.按红灯,将墨盒移动到右侧空处 2.按住连供顶部的重置小按钮 15秒以上,复位(这个应该是让连供墨盒产生一个另外的墨盒序号,骗打印机换了个新墨盒) 3.按打印机红灯, ...

  7. win7开机启动项设置

    Windows系统自身就有启动项命令可以进行设置: 要说到修改启动项,当然首推Windows系统自带的“MSCONFIG”命令,XP等其他Windows系统用户使用方法是一模一样的. 1.点击“开始” ...

  8. springmvc下载一个文档下载接口里的文档

    A提供了一个文件下载的接口,在调用的时候可以直接在前端用a标签来调用 <a href="http://" target="_blank">下载< ...

  9. ubuntu上用源码进行一键安装mysql

      首先卸载原有的mysql: 首先查看自己的mysql有哪些依赖 #dpkg --list|grep mysql 先卸载 #sudo apt-get remove mysql-common #sud ...

  10. 阿里云出手SaaS生态,中国SaaS市场小而不强有望破解

    企业服务SaaS市场还有很大的增长空间.SaaS的鼻祖Salesforces今年5月迈上了千亿美元市值的门槛,再一次为ToB市场注入了兴奋剂.单单一个SaaS CRM,目前全球的市场规模就超过400亿 ...