hdu2196树形dp

有一棵树,找每个节点所能到达的最远距离是多少

dis[u][0]正向最大距离    dis[u][1]正向次大距离     dis[u][2]反向最大距离

先一边dfs求出每个节点的正向最大距离(就是向下)和次向最大距离,以及longest记录下当前节点的正向最大距离路径的子节点(为了第二遍dfs,判断这一条路是不是正向最大距离)

再进行第二遍dfs,v是u 的子节点,如果v在u的正向最大距离路径里(即longest[u]=v)那么v的最大反向距离就是max(u的最大反向距离,u的正向次大距离)+w【u】【v】

如果v不在u 的正向最大距离路径里,那么v的最大反向距离就是max(u的最大反向距离,u的正向最大距离)+w【u】【v】

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<cassert>
#include<iomanip>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define pi acos(-1)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#pragma comment(linker, "/STACK:1024000000,1024000000")

using namespace std;

const double g=10.0,eps=1e-9;
const int N=10000+10,maxn=500+100,inf=0x3f3f3f;

struct edge{
    int to,Next,w;
}e[N*2];
int cnt,Head[N];
int longest[N],dis[N][3];//0正向最大距离,1正向次大距离,2反向最大距离
void add(int u,int v,int w)
{
    e[cnt].to=v;
    e[cnt].w=w;
    e[cnt].Next=Head[u];
    Head[u]=cnt++;
}
int dfs1(int u,int fa)//返回u的正向最大距离,fa是u的父节点
{
    if(dis[u][0]>0)return dis[u][0];
    dis[u][0]=dis[u][1]=dis[u][2]=longest[u]=0;
    for(int i=Head[u];~i;i=e[i].Next)
    {
        int v=e[i].to;
        if(v==fa)continue;
        if(dis[u][0]<dfs1(v,u)+e[i].w)//v是u的最大距离中的一个子节点
        {
            longest[u]=v;
            dis[u][1]=max(dis[u][1],dis[u][0]);//此时dis[u][0]就是一个可能的次大节点了
            dis[u][0]=dfs1(v,u)+e[i].w;
        }
        else if(dis[u][1]<dfs1(v,u)+e[i].w)
            dis[u][1]=max(dis[u][1],dfs1(v,u)+e[i].w);
    }
    return dis[u][0];
}
int dfs2(int u,int fa)
{
    for(int i=Head[u];~i;i=e[i].Next)
    {
        int v=e[i].to;
        if(v==fa)continue;
        if(longest[u]==v)dis[v][2]=max(dis[u][2],dis[u][1])+e[i].w;
        else dis[v][2]=max(dis[u][2],dis[u][0])+e[i].w;
        dfs2(v,u);
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    while(cin>>n){
        cnt=0;
        memset(Head,-1,sizeof Head);
        memset(dis,-1,sizeof dis);
        memset(longest,-1,sizeof longest);
        for(int i=2;i<=n;i++)
        {
            int v,w;
            cin>>v>>w;
            add(i,v,w);
            add(v,i,w);
        }
        dfs1(1,-1);
        dfs2(1,-1);
        for(int i=1;i<=n;i++)
            cout<<max(dis[i][0],dis[i][2])<<endl;
    }
    return 0;
}
/*
longest[i]=j代表i在子树中的最大距离经过了j节点
*/
树形dp
原文地址:https://www.cnblogs.com/acjiumeng/p/7182073.html