树形DP——HDU2196

题目链接

题目含义

找出每台电脑距离最远电脑的长度

题目分析

对于节点v来说,如果最长长度在它的子树里,我们取dp[u][0]

否则,最长长度要经过它的父节点u,v的最长长度=dis(u,v)+u的最长长度

第一种情况,如果u的最长长度经过v这个子节点,那么很明显最长长度不可取,那我们就要去第二长长度dp[u][1]

第二种情况,如果u的最长长度不经过v这个子节点,那么就取u的最长长度dp[u][0]

所以每一个节点,都要求子树最长距离dp[u][0],第二长距离dp[u][1]

为了计算方便,还要求经过父节点的最长距离dp[u][2]

更详细的过程可以看这个博主的博客

题目代码

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
const int maxn=1e4+7;
int n,q,a,b,c,tot;
int head[maxn],dp[maxn][3],longest[maxn];
struct node{
    int to,w,next;
}edge[maxn*2];
void add(int u,int v,int w){
    edge[tot].to=v;
    edge[tot].w=w;
    edge[tot].next=head[u];
    head[u]=tot++;
}
int dfs1(int u,int fa){
    if(dp[u][0]>=0)return dp[u][0];
    dp[u][0]=dp[u][1]=dp[u][2]=longest[u]=0;
    for(int i=head[u];i!=-1;i=edge[i].next){
        int v=edge[i].to;
        if(v==fa)continue;
        if(dp[u][0]<dfs1(v,u)+edge[i].w){
            dp[u][1]=dp[u][0];
            dp[u][0]=dfs1(v,u)+edge[i].w;
            longest[u]=v;
        }
        else if(dp[u][1]<dfs1(v,u)+edge[i].w){
            dp[u][1]=dfs1(v,u)+edge[i].w;
        }
    }
    return dp[u][0];
}
void dfs2(int u,int fa){
    for(int i=head[u];i!=-1;i=edge[i].next){
        int v=edge[i].to;
        if(v==fa)continue;
        if(v==longest[u])dp[v][2]=max(dp[u][1],dp[u][2])+edge[i].w;
        else dp[v][2]=max(dp[u][0],dp[u][2])+edge[i].w;
        dfs2(v,u);
    }
}
int main(){
    while(~scanf("%d",&n)){
        tot=0;
        memset(head,-1,sizeof(head));
        memset(dp,-1,sizeof(dp));
        memset(longest,-1,sizeof(longest));
        for(int i=2;i<=n;i++){
            scanf("%d%d",&a,&b);
            add(a,i,b)/*,add(i,a,b)*/;
        }
        dfs1(1,0);
        dfs2(1,0);
        for(int i=1;i<=n;i++)
            printf("%d\n",max(dp[i][0],dp[i][2]));
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/helman/p/11273176.html