题目链接:点击打开链接
题意描述:给定一棵树,树上每条边的有一个权值,问从任意一个点出发能走得最长路径是多少?
解题思路:树上最长路径 dp
1、任意找一个点作为根节点,将无根树转化为有根树
2、在dfs过程中更新f[i],g[i],其中f[i]记录以i为节点向下扩展最长路,g[i]为次长路,并用mark标记每个节点最长路的儿子节点
3、在dfs1的过程中更新h[i],h[i]表示以i为节点的向上扩展的最长路
代码:
#pragma comment(linker,"/STACK:1024000000,1024000000")
#include <cstdio>
#include <cstring>
#include <iostream>
#define MAXN 10010
using namespace std;
int head[MAXN],tol;
struct Edge{
int to,v,next;
}edge[2*MAXN];
void addEdge(int f,int t,int v){
edge[tol].to=t;edge[tol].v=v;edge[tol].next=head[f];head[f]=tol++;
edge[tol].to=f;edge[tol].v=v;edge[tol].next=head[t];head[t]=tol++;
}
int max(int a,int b){
return a>b?a:b;
}
int f[MAXN],g[MAXN],h[MAXN];
int mark[MAXN];
void dfs(int u,int p){
f[u]=0;g[u]=0;mark[u]=-1;
int k,to;
for(k=head[u];k!=-1;k=edge[k].next){
to=edge[k].to;
if(to==p) continue;
dfs(to,u);
if(f[u]<=f[to]+edge[k].v){
mark[u]=to;
g[u]=f[u];///
f[u]=f[to]+edge[k].v;
}
if(g[u]<=f[to]+edge[k].v&&mark[u]!=to) g[u]=f[to]+edge[k].v;///
}
}
void dfs1(int u,int p){
int k,to;
for(k=head[u];k!=-1;k=edge[k].next){
to=edge[k].to;
if(to==p) continue;
if(mark[u]!=to)
h[to]=max(h[u],f[u])+edge[k].v;
else
h[to]=max(h[u],g[u])+edge[k].v;
dfs1(to,u);
}
}
int n;
int main(){
while(scanf("%d",&n)!=EOF){
tol=0;memset(head,-1,sizeof(head));
int t,v;
for(int i=2;i<=n;++i){scanf("%d%d",&t,&v);addEdge(i,t,v);}
dfs(1,1);
memset(h,0,sizeof(h));
dfs1(1,1);h[1]=g[1];///此处更新根节点
for(int i=1;i<=n;++i) printf("%d\n",max(h[i],f[i]));
}
return 0;
}
/*
9
1 1
1 2
2 4
2 5
3 6
1 3
7 7
8 8
*/