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

Computer(HDU2196)——树形dp的那些事

时间:2017-10-29 16:41:52      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:距离   eof   problem   树的直径   pid   com   父节点   turn   computer   

让我们先附上原题链接

??

这个题目的题意翻译过来差不多就是求树上每一个节点在树上的最远距离。其实这题目有两个做法
一个是求树的直径,一个是用树形dp,但是这里只说树形dp的方法,求直径的方法思路还是比较简单的。

对于树形dp我们有以下的思路,对于一个节点root在树上的最长路径,有两种可能。一:此路径在以root为根节点的子树上,二:此路径经过其父节点。所以我们可以将树设为以1为根,然后进行两次dfs,第一次求出以x为起点并在其子树内的最长路径以及次长路径。之后第二次dfs求出经过x父节点的最长路径。思路就是这样了。接下来贴代码。

#include
#include
#include
using namespace std;
struct nob{
	int sta,ed,val,jump;
}a[20005];
int n,jump[10005],num,fa[10005],dp[10005][3];
//dp[x][0]表示子树内最长路径,dp[x][1]表示子树内次长路径,dp[x][2]表示经过父节点的最长路径 
void add(int sta,int ed,int val){
	num++;
	a[num].sta=sta;
	a[num].ed=ed;
	a[num].val=val;
	a[num].jump=jump[sta];
	jump[sta]=num;
}
void dfs1(int pos){
	dp[pos][0]=0;
	dp[pos][1]=0;
	dp[pos][2]=0;
	for (int i=jump[pos]; i; i=a[i].jump){
		dfs1(a[i].ed);
		if (dp[a[i].ed][0]+a[i].val>=dp[pos][1]){
			dp[pos][1]=dp[a[i].ed][0]+a[i].val;
			if (dp[pos][0]<dp[pos][1]) swap(dp[pos][0],dp[pos][1]);
		}
	}
}
void dfs(int pos){
	for (int i=jump[pos]; i; i=a[i].jump){
		if (dp[pos][0]==dp[a[i].ed][0]+a[i].val){
			dp[a[i].ed][2]=max(dp[pos][2],dp[pos][1])+a[i].val;
		}
		else{
			dp[a[i].ed][2]=max(dp[pos][2],dp[pos][0])+a[i].val;
		}
		dfs(a[i].ed);
	}
}
int main(){
	while(~scanf("%d",&n)){
		num=0;
		memset(jump,0,sizeof(jump));
		for (int i=2,x,y; i<=n; i++){
			scanf("%d%d",&x,&y);
			add(x,i,y);
		}
		dfs1(1);
		dfs(1);
		for (int i=1; i<=n; i++){
			printf("%d\n",max(dp[i][0],dp[i][2]));
		}	
	}
	
	return 0;
}

Computer(HDU2196)——树形dp的那些事

标签:距离   eof   problem   树的直径   pid   com   父节点   turn   computer   

原文地址:http://www.cnblogs.com/cain-/p/7750246.html

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