hdu 2196 Computer

http://acm.hdu.edu.cn/showproblem.php?pid=2196

网上说这是经典的树形dp,要两次dfs即可……每个节点记录距离该节点最远的距离次远的距离,个人比较懒不写这么详细了

总结: 一个节点除了从孩子传递过来的信息外,还要考虑从父亲节点传过来的信息

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>

using namespace std;
typedef long long ll;
const int maxn=100010;
vector<pair<int,ll> > g[maxn];
vector<pair<int,ll> > dp[maxn];

void ins(int u,pair<int,ll> tmp)
{
    if(dp[u].size()==0) dp[u].push_back(tmp);
    else if(dp[u].size()==1){
        if(dp[u][0].second>=tmp.second) dp[u].push_back(tmp);
        else{
           pair<int,ll> dd=dp[u][0];
           dp[u][0]=tmp;
           dp[u].push_back(dd);
        }
    }else{
       if(tmp.second>=dp[u][0].second) dp[u][1]=dp[u][0],dp[u][0]=tmp;
       else if(tmp.second>dp[u][1].second) dp[u][1]=tmp;
    }
}
void dfs1(int u,int fa)
{
    dp[u].clear();
    bool mark=1;
    for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i].first;
        ll len=g[u][i].second;
        if(v==fa) continue;
        mark=0;
        dfs1(v,u);
        ins(u,make_pair(v,dp[v][0].second+len));
    }
    if(mark) dp[u].push_back(make_pair(0,0));
}
void dfs2(int u,int fa)
{
    for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i].first;
        ll len=g[u][i].second;
        if(v==fa) continue;
        if(dp[u][0].first!=v) ins(v,make_pair(u,len+dp[u][0].second));
        else if(dp[u].size()>1) ins(v,make_pair(u,len+dp[u][1].second));
        else ins(v,make_pair(u,len));
        dfs2(v,u);
    }
}
int main()
{
    int n,a;
    ll b;
    while(scanf("%d",&n)==1)
    {
        for(int i=2;i<=n;i++)
        {
            scanf("%d%I64d",&a,&b);
            g[a].push_back(make_pair(i,b));
            g[i].push_back(make_pair(a,b));
        }
        dfs1(1,-1);
        dfs2(1,-1);
        for(int i=1;i<=n;i++)
        {
            printf("%I64d\n",dp[i][0].second);
            g[i].clear();
        }
    }
    return 0;
}


你可能感兴趣的:(hdu 2196 Computer)