【树形DP】 HDU 2196 Computer

题意:求节点间的最大距离


先DFS一次 记录下 每一节点的子树下的最大距离(DP[ u ] [ 0 ])和第二大距离(DP[ u ] [ 1 ])

用DP[ v ] [ 2 ] 表示由v的父节点来的最大距离

再取DP[ u ] [ 0 ] 与 DP[ u ][ 2 ] 的最值

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <cmath>
using namespace std;
#include <queue>
#include <stack>
#include <vector>
#include <deque>
#include <set>
#include <map>
#include <time.h>;
#define cler(arr, val)    memset(arr, val, sizeof(arr))
#define FOR(i,a,b)  for(int i=a;i<=b;i++)
#define IN   freopen ("in.txt" , "r" , stdin);
#define OUT  freopen ("out.txt" , "w" , stdout);
typedef long long  LL;
const int MAXN = 10014;
const int MAXM = 20014;
const int INF = 0x3f3f3f3f;
const int mod = 1000000007;
struct node
{
    int v,next;
    LL val;
} edge[MAXM];
int head[MAXM],tol;
LL dp[MAXN][3];
bool vis[MAXN];
void init()
{
    cler(head,-1);
    tol=0;
}
void addedge(int u,int v,LL val)
{
    edge[tol].v=v,edge[tol].val=val,edge[tol].next=head[u];
    head[u]=tol++;
    edge[tol].v=u,edge[tol].val=val,edge[tol].next=head[v];
    head[v]=tol++;
}
void dfs1(int u)
{
    if(vis[u]) return ;
    vis[u]=true;
    for(int i=head[u]; ~i; i=edge[i].next)
    {
        int v=edge[i].v;
        if(!vis[v])
        {
            dfs1(v);
            dp[u][1]=max(dp[u][1],dp[v][0]+edge[i].val);
            if(dp[u][1]>dp[u][0])swap(dp[u][1],dp[u][0]);
        }
    }
}
void dfs2(int u)
{
    if(vis[u]) return ;
    vis[u]=true;
    for(int i=head[u]; ~i; i=edge[i].next)
    {
        int v=edge[i].v,val=edge[i].val;
        if(!vis[v])
        {
            if(dp[u][0]>dp[v][0]+val)//dp[u][0]不是由dp[v][0]+val而来的
                dp[v][2]=max(dp[v][2],max(dp[u][0]+val,dp[u][2]+val));//所以从非v子树来的更长
            else //dp[u][0]由dp[v][0]+val而来的
                dp[v][2]=max(dp[v][2],max(dp[u][1]+val,dp[u][2]+val));//推断非v子树来的哪个长
            dfs2(v);
        }
    }
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    int n;
    while(~scanf("%d",&n))
    {
        init();
        for(int i=2; i<=n; i++)
        {
            int a;
            LL b;
            scanf("%d %I64d",&a ,&b );
            addedge(i,a,b);
        }
        cler(vis,false);
        cler(dp,0);
        dfs1(1);
        cler(vis,false);
        dfs2(1);
        for(int i=1;i<=n;i++)
            printf("%I64d\n",max(dp[i][2],dp[i][0]));
    }

}


posted @ 2017-06-28 20:38  gccbuaa  阅读(134)  评论(0编辑  收藏  举报