hdu2196

树形dp经典题

考虑只维护一个最长路会使得所选路径重复

因此可以再维护一个次长路来消除路径重复...

然后这题就结束了

#include<bits/stdc++.h>
#define MAXN 10005
using namespace std;

int n,tot;
int h[MAXN],f[MAXN][3],fr[MAXN];

struct node{
    int from,to,cost,next;
}e[MAXN<<1];

void init(){
    tot=0;
    memset(h,-1,sizeof(h));
    memset(f,0,sizeof(f));
    memset(fr,0,sizeof(fr));
}

void add(int x,int y,int z){
    tot++;
    e[tot].from=x;
    e[tot].to=y;
    e[tot].cost=z;
    e[tot].next=h[x];
    h[x]=tot;
}

void dfs(int now,int fa){
    int mx=0,mr=0;//max maxl
    for(int i=h[now];i!=(-1);i=e[i].next){
        if(e[i].to!=fa){
            dfs(e[i].to,now);
            if(mx<f[e[i].to][0]+e[i].cost)mr=mx,mx=f[e[i].to][0]+e[i].cost,fr[now]=e[i].to;
            else if(mr<f[e[i].to][0]+e[i].cost)mr=f[e[i].to][0]+e[i].cost;
        }
    }
    f[now][0]=mx;
    f[now][1]=mr;
}

void dfs2(int now,int fa){
    for(int i=h[now];i!=(-1);i=e[i].next){
        if(e[i].to!=fa){
        f[e[i].to][2]=max(f[e[i].to][2],f[now][2]+e[i].cost);
        if(fr[now]!=e[i].to)f[e[i].to][2]=max(f[e[i].to][2],f[now][0]+e[i].cost);
        else f[e[i].to][2]=max(f[e[i].to][2],f[now][1]+e[i].cost);    
        dfs2(e[i].to,now);
        }
    }
}
    
int main(){
    while(scanf("%d",&n)==1){
        init();
        for(int i=2;i<=n;i++){
            int p,c;cin>>p>>c;
            add(p,i,c);
            add(i,p,c);
        }
        dfs(1,1);
        dfs2(1,1);
        for(int i=1;i<=n;i++){
            cout<<max(max(f[i][0],f[i][1]),f[i][2])<<endl;
        }
    }
}
View Code

经验:再一些情况下,解决重复问题可以采用维护次答案来解决....

或者通过设计一些不会重复的状态....

更或者是根据状态来解决重复

或者通过一些特殊手段(数学?  重新构造一个....或者是逐步去重(比较玄学))

原文地址:https://www.cnblogs.com/shatianming/p/12300489.html