Computer HDU - 2196(树形dp)

题目要求:求树上每个点能到达的最远距离

dp[u][0]:u的子树下u的最远距离是多少

dp[u][1]:u的子树次远距离是多少

dp[u][2]:u的父亲能走的最远距离是多少

dp[0] [1]dfs处理即可

如果vi不是u最长距离经过的节点,f[vi][1] = dist(vi,u)+max(f[u][0], f[u][1])
如果vi是u最长距离经过的节点,那么不能选择f[u][0],因为这保存的就是最长距离,要选择u次大距离

#include<bits/stdc++.h>

#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;

const int maxn=1e5+10;

struct edge{
    int u,v,w,next;
}e[maxn];

int g[maxn],tot=0;

int dp[maxn][3];

void creat_edge(int u,int v,int w)
{
    e[++tot]=(edge){u,v,w,g[u]};
    g[u]=tot;
}

void dfs(int u)//递归求得u子树中的最大与次大 0最大 1次大
{
    for(int i=g[u];i>0;i=e[i].next)
    {
        int v=e[i].v;
        dfs(v);
        int w=e[i].w;
        int temp= dp[v][0]+w;
        if(temp>=dp[u][0])
        {
            dp[u][1]=dp[u][0];
            dp[u][0]=temp;
        }
        else if(temp>dp[u][1])
            dp[u][1]=temp;
    }
}

void dfs1(int u)
{
    for(int i=g[u];i>0;i=e[i].next)
    {
        int v=e[i].v,w=e[i].w;
        if(dp[u][0]==dp[v][0]+w)//如果当前节点在最大路径上 只能取次大路径
            dp[v][2]=max(dp[u][2],dp[u][1])+w;
        else
            dp[v][2]=max(dp[u][2],dp[u][0])+w;
        dfs1(v);
    }
}

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        mem(g,0);
        mem(dp,0);
        for(int i=2;i<=n;i++)
        {
            int u=i,v,w;
            scanf("%d%d",&v,&w);
            creat_edge(v,u,w);
        // creat_edge(v,u,w);
        }
        dfs(1);
        dfs1(1);
        for(int i=1;i<=n;i++)
            cout<<max(dp[i][0],dp[i][2])<<"\n";
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/minun/p/10806651.html