hdu 2196 (树形DP)

来源:互联网 发布:php程序员发展前景 编辑:程序博客网 时间:2024/05/29 11:58

题意:在一个树中,边会有不同的距离,求每一个结点到其它所有结点中最远的距离。


思路:直接一次DFS很难求出其转换的关系。所以用两次DFS

           第一次DFS是找到当前结点往下能到的最远距离

           第二次DFS是更新从父结点到该点是否有更远的距离

           这里会记录最大距离和次最大距离,主要用于更新到旁路最长距离时用。

           注意顺便记录到最长距离的下一个结点的编号。


#include <stdio.h>#include <string.h>#include<cmath>#include<iostream>#include<algorithm>#include<queue>#include<vector>#include<malloc.h>#include<string>using namespace std;const int N=10001;int n,m;struct my{int next,w;my(){}my(int a,int b){next=a,w=b;}};vector<my> edge[N];int dp[N][2],dpid[N][2];void dfs1(int cur,int pre){//cout<<cur<<' '<<pre<<endl;for (int i=0;i<edge[cur].size();i++){my son=edge[cur][i];if (son.next == pre) continue;dfs1(son.next,cur);if (dp[cur][0] < dp[son.next][1]+son.w) dp[cur][0]=dp[son.next][1]+son.w,dpid[cur][0]=son.next;if (dp[cur][0] > dp[cur][1]) swap(dp[cur][0],dp[cur][1]),swap(dpid[cur][0],dpid[cur][1]);}}void dfs2(int cur,int pre){for (int i=0;i<edge[cur].size();i++){my son=edge[cur][i];if (son.next == pre) continue;if (son.next == dpid[cur][1]){if (son.w+dp[cur][0] > dp[son.next][0]) dp[son.next][0]=son.w+dp[cur][0],dpid[son.next][0]=cur;if (dp[son.next][0] > dp[son.next][1]) swap(dp[son.next][0],dp[son.next][1]),swap(dpid[son.next][0],dpid[son.next][1]);}else{if (son.w+dp[cur][1] > dp[son.next][0]) dp[son.next][0]=son.w+dp[cur][1],dpid[son.next][0]=cur;if (dp[son.next][0] > dp[son.next][1]) swap(dp[son.next][0],dp[son.next][1]),swap(dpid[son.next][0],dpid[son.next][1]);}dfs2(son.next,cur);}}int main(){freopen("in","r",stdin);while (cin>>n){for (int i=1;i<=n;i++) edge[i].clear(),dp[i][0]=dp[i][1]=0;for (int i=2;i<=n;i++){int a,b;scanf("%d%d",&a,&b);edge[i].push_back(my(a,b));edge[a].push_back(my(i,b));}dfs1(1,-1);//for (int i=1;i<=n;i++) printf("%d\n",dp[i][1]);dfs2(1,-1);for (int i=1;i<=n;i++) printf("%d\n",dp[i][1]);}}


0 0