• 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
  • 相关阅读:
    HDU 1114 Piggy-Bank
    HDU 2955 Robberies
    NTOJ 290 动物统计(加强版)
    POJ 3624 Charm Bracelet
    HDU 2602 Bone Collector
    POJ 1523 SPF(无向图割顶)
    HDU 5311 Hidden String
    HDU 1421 搬寝室
    HDU 1058 Humble Numbers
    POJ 3259 Wormholes(spfa判负环)
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/7182073.html
Copyright © 2020-2023  润新知