其他分享
首页 > 其他分享> > hdu 2196

hdu 2196

作者:互联网

给一棵树,每条边有权值,对于每个点,求到该点的路径的最大权值。
树形dp
对于一个节点来说,到它的最大路径权值要么是它的子树中的节点到该点,要么是父亲节点的其他子树节点到该点。
dp[i][0] 表示以i为根节点的子树中到 i 的最大路径权值
dp[i][1] 表示以i为根节点的子树中到 i 的最大路径权值
dp[i][2] 表示i的父亲节点的除了i这棵子树外的其他子树到i的最大路径权值
dp[i][0]和dp[i][1]一次dfs解决
dp[i][2]计算时要判断i是否在i的父节点的最长的路径上。

#include <cstdio>
#include <algorithm>
#include <vector>
#define f first
#define s second
using namespace std;
const int N = 10000 + 10;
typedef pair<int,int> PII; 
vector<PII> G[N];
int n,u,w,dp[N][3];
void dfs1(int u,int fa){
	dp[u][0] = 0;
	dp[u][1] = 0;
	for(int i = 0;i<G[u].size();i++){
		int v = G[u][i].f;
		if(v == fa) continue;
		dfs1(v,u);
		if(dp[v][0] + G[u][i].s > dp[u][0]) 
			dp[u][1] = dp[u][0], dp[u][0] = dp[v][0] + G[u][i].s;
		else if(dp[v][0] + G[u][i].s > dp[u][1]) 
			dp[u][1] = dp[v][0] + G[u][i].s;
	}
}
void dfs2(int u,int fa){
	for(int i = 0;i<G[u].size();i++){
		int v = G[u][i].f;
		if(v == fa) continue;
		if(dp[u][0] == dp[v][0] + G[u][i].s) 
			dp[v][2] = max(dp[u][2],dp[u][1]) + G[u][i].s; 
		else dp[v][2] = max(dp[u][0],dp[u][2]) + G[u][i].s;
		dfs2(v,u);
	}
} 
int main(){
	while(~scanf("%d",&n)){
		for(int i = 1;i<=n;i++) G[i].clear();
		for(int i = 2;i<=n;i++){
			scanf("%d%d",&u,&w);
			G[i].push_back({u,w});
			G[u].push_back({i,w}); 
		}
		dfs1(1,-1);
		dfs2(1,-1);
		for(int i = 1;i<=n;i++)
			printf("%d\n",max(dp[i][0],dp[i][2])); 
	}
	return 0;
}

标签:hdu,子树,int,路径,2196,权值,节点,dp
来源: https://blog.csdn.net/winhcc/article/details/89189275