hdu2196树形dp求任一点的最长路

来源:互联网 发布:网络维护公司简介 编辑:程序博客网 时间:2024/05/18 06:23

如果用spfa,复杂度O(n*n*lgn),超时

解题思路:先求出某一根节点的结果,然后用该结果去算出子节点的结果,以此类推。在计算的过程中不断维护最长路及次长路

#include<stdio.h>#include<string.h>#include<string>#include<algorithm>#include<iostream>#include<set>#include<map>#include<queue>#include<stack>#include<vector>#include<math.h>#include<stdlib.h>using namespace std;#define M 10005bool mark[M];int dp[M][2],head[M],tot;struct node {int to,next,weight;}line[2*M]; void add(int u,int v,int weight){line[tot].to=v;line[tot].weight=weight;line[tot].next=head[u];head[u]=tot++;}int dfs(int u)//求出以u为根的子树的最长路及次长路 {int mx=0,i,j,k,cmx=0;mark[u]=1;for(i=head[u];i!=-1;i=line[i].next){if(mark[line[i].to]==1)continue;k=dfs(line[i].to)+line[i].weight;if(k>mx){cmx=mx;mx=k;}else if(k>cmx){cmx=k;}}dp[u][0]=mx;dp[u][1]=cmx;return mx;}void solve(int u)//用1为根求出的结果来更新其他节点的最长路和次长路 {int cmx=0,i,j,k,mx=0;mark[u]=1;for(i=head[u];i!=-1;i=line[i].next){if(mark[line[i].to]==1)continue;if(dp[line[i].to][0]+line[i].weight!=dp[u][0]){dp[line[i].to][1]=dp[line[i].to][0];dp[line[i].to][0]=dp[u][0]+line[i].weight;}else{k=dp[u][1]+line[i].weight;if(k>dp[line[i].to][0]){dp[line[i].to][1]=dp[line[i].to][0];dp[line[i].to][0]=k;}else if(k>dp[line[i].to][1]){dp[line[i].to][1]=k;}}solve(line[i].to);}return;}int main(){int i,j,k,n,m,weight,u;while(scanf("%d",&n)!=EOF){tot=0;memset(mark,0,sizeof(mark));memset(dp,0,sizeof(dp));memset(head,-1,sizeof(head));for(i=2;i<=n;i++)//这里的输入比较少见 {scanf("%d%d",&u,&weight);add(i,u,weight);add(u,i,weight);}dfs(1);memset(mark,0,sizeof(mark));solve(1);for(i=1;i<=n;i++)printf("%d\n",dp[i][0]);}return 0;}


原创粉丝点击