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