1. 程式人生 > >[樹形DP]HDU 2196-Computer

[樹形DP]HDU 2196-Computer

() 表示 裏的 其他 tchar long struct 更新 如果

題目大意

求樹中每個點到任意點的最長距離

思路

該距離有兩種,一種是經過父親節點的,一種是子樹裏的
定義dp[x][0/1]表示x到葉子節點的最大距離和次大距離
dp[x][2]表示經過父親節點的最長路徑
dp[x][2]可以是先走到父親節點,再走到父親的其他兒子,也可能是走到父親節點再走到父親的父親
此時若父親的最遠葉子節點經過該點,就用次大值更新,否則用最大值更新

#include<cstdio>
#include<cstring>
#include<iostream>
#define max(a,b) ((a)>(b)?(a):(b))
typedef long long ll;
const int maxn=10000+5;
inline int Read(){
    int x=0;char c=getchar();
    while(‘0‘>c||c>‘9‘)c=getchar();
    while(‘0‘<=c&&c<=‘9‘)x=(x<<1)+(x<<3)+c-48,c=getchar();
    return x;
}
struct Edge{
    int to,nxt,data;
}e[maxn<<1];
int n,head[maxn],cnt,dp[maxn][3];
inline void Insert(int x,int y,int z){
    e[++cnt].to=y;e[cnt].data=z;
    e[cnt].nxt=head[x];head[x]=cnt;
}
#define y e[i].to
void Dfs1(int x){
    dp[x][0]=dp[x][1]=dp[x][2]=0;
    for(int i=head[x];i;i=e[i].nxt){
        Dfs1(y);
        if(dp[y][0]+e[i].data>dp[x][0]){
            dp[x][1]=dp[x][0];
            dp[x][0]=dp[y][0]+e[i].data;//dp[x][0]表示x到子樹內葉節點的最長距離
        }
        else dp[x][1]=max(dp[x][1],dp[y][0]+e[i].data);//dp[x][1]表示次長距離
    }
}
void Dfs2(int x){
    for(int i=head[x];i;i=e[i].nxt){
        if(dp[x][0]==dp[y][0]+e[i].data)
            dp[y][2]=max(dp[x][1],dp[x][2])+e[i].data;
        else dp[y][2]=max(dp[x][0],dp[x][2])+e[i].data;
        Dfs2(y);
    }//dp[x][2]表示經過父節點取得的最長路徑,此時可以到父親節點再到父親的其他兒子,也可以從父親到父親的父親
    //如果父節點到葉子節點的最大值經過y,那麽就用次大值更新,否則就用最大值
}
#undef y
int main(){
    int x,y;
    while(scanf("%d",&n)!=EOF){
        cnt=0;
        memset(head,0,sizeof(head));
        for(int i=2;i<=n;++i)x=Read(),y=Read(),Insert(x,i,y);
        Dfs1(1);Dfs2(1);
        for(int i=1;i<=n;++i)printf("%d\n",max(dp[i][0],dp[i][2]));
    }
    return 0;
}

[樹形DP]HDU 2196-Computer