标签:
题目链接:点击打开链接
题意描述:给定一棵树,树上每条边的有一个权值,问从任意一个点出发能走得最长路径是多少?
解题思路:树上最长路径 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); 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 */
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/mengxingyuanlove/article/details/48008109