hdu2196(求每一点在树上最远距离)

题意:如标题所示 ,在一棵无根树上求每一点的最远距离,poj1985(求树上直径(最远两点距离))加强版。
思路: 无根树随便找一点看作有根树。
定义:dp[i][0]:i点作为根的子树到其他点的最远距离
dp[i][1]:i点作为根的子树到其他点的次远距离
dp[i][2]:i点到他祖先的最远距离

考虑一遍dfs从叶子到根的顺序可以先求dp[i][0] 表示以i为根的子树到根的最远距离,随带把次大的距离也求了(当然有用).再思考一下,对于单个点v他往子孙方向上最远距离(dp[v][0])已求出,他的祖先里到他的最远距离(dp[v][2])却未知,如果都知道只要选取这两者的最大值。
思考一下:如果他父亲作为根到子孙的最远距离(dp[i][0])经过它,那么只能就是选择他父亲第二远的距离作为比较,如果没有经过,就用他父亲最远的点更新。

#include<bits/stdc++.h>
using namespace std;
const int maxn=10000+10;

template<int N,int M>//N点的个数,M边的个数
struct Graph
{
    int top;
    struct Vertex{
        int head;
    }V[N];
    struct Edge{
        int v,w,next;
    }E[M];
    void init(){
        memset(V,-1,sizeof(V));
        top = 0;
    }
    void add_edge(int u,int v,int w){
        E[top].v = v;
        E[top].w=w;
        E[top].next = V[u].head;
        V[u].head = top++;
    }
};
Graph<maxn,maxn> g;
int n,dp[maxn][3];

void dfs1(int u,int f){//求u为根的所有子树到根的最远距离
   for(int i=g.V[u].head;i!=-1;i=g.E[i].next){
       int v=g.E[i].v,len=g.E[i].w;
       if(v==f) continue;
       dfs1(v,u);
       if(dp[v][0]+len>=dp[u][0]){
          dp[u][1]=dp[u][0];
          dp[u][0]=dp[v][0]+len;
       }
       else if(dp[v][0]+len>dp[u][1]) dp[u][1]=dp[v][0]+len;
   }
}

void dfs2(int u,int f){//求u为儿子,他的所有祖先到他的最远距离
   for(int i=g.V[u].head;i!=-1;i=g.E[i].next){
      int v=g.E[i].v,len=g.E[i].w;
      if(v==f) continue;
      dp[v][2]=max(dp[u][2],dp[v][0]+len==dp[u][0]? dp[u][1] : dp[u][0])+len;
      dfs2(v,u);
   }
}



int main(){
   while(~scanf("%d",&n)){
     g.init();
     for(int i=2;i<=n;i++){
        int a,v;scanf("%d%d",&a,&v);
        g.add_edge(a,i,v);
     }
     memset(dp,0,sizeof(dp));
     dfs1(1,-1);
     dfs2(1,-1);
     for(int i=1;i<=n;i++) printf("%d\n",max(dp[i][0],dp[i][2]));
   }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值