hdu-5834 Magic boy Bi Luo with his excited tree(树形dp)

题目链接:

Magic boy Bi Luo with his excited tree

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1037    Accepted Submission(s): 298


Problem Description
Bi Luo is a magic boy, he also has a migic tree, the tree has N nodes , in each node , there is a treasure, it's value is V[i], and for each edge, there is a cost C[i], which means every time you pass the edge i , you need to pay C[i].

You may attention that every V[i] can be taken only once, but for some C[i] , you may cost severial times.

Now, Bi Luo define ans[i] as the most value can Bi Luo gets if Bi Luo starts at node i.

Bi Luo is also an excited boy, now he wants to know every ans[i], can you help him?
 
Input
First line is a positive integer T(T104) , represents there are T test cases.

Four each test:

The first line contain an integer N(N105).

The next line contains N integers V[i], which means the treasure’s value of node i(1V[i]104).

For the next N1 lines, each contains three integers u,v,c , which means node u and node v are connected by an edge, it's cost is c(1c104).

You can assume that the sum of N will not exceed 106.
 
Output
For the i-th test case , first output Case #i: in a single line , then output N lines , for the i-th line , output ans[i] in a single line.
 
Sample Input
1
5
4 1 7 7 7
1 2 6
1 3 1
2 4 8
3 5 2
 
Sample Output
Case #1:
15
10
14
9
15
 
题意:
 
每个节点有价值v[i]的宝物,但是任何两个节点u,v之间的路走一次花费为w,从每个节点出发最多可以赚多少钱;
 
思路:
 
树形dp的题目,需要记录转移的最大和次大,注意转移的情况,不能写漏了;
 
AC代码:
 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <bits/stdc++.h>
#include <stack>
#include <map>
  
using namespace std;
  
#define For(i,j,n) for(int i=j;i<=n;i++)
#define mst(ss,b) memset(ss,b,sizeof(ss));
  
typedef  long long LL;
  
template<class T> void read(T&num) {
    char CH; bool F=false;
    for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
    for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
    F && (num=-num);
}
int stk[70], tp;
template<class T> inline void print(T p) {
    if(!p) { puts("0"); return; }
    while(p) stk[++ tp] = p%10, p/=10;
    while(tp) putchar(stk[tp--] + '0');
    putchar('
');
}
  
const int mod=1e9+7;
const double PI=acos(-1.0);
const int inf=1e9;
const int N=(1<<20)+10;
const int maxn=1e5+110;
const double eps=1e-12;
 

int n,cnt,head[maxn],a[maxn];
int down[maxn][2],up[maxn][2],max1[maxn],max2[maxn],temp[maxn],cost[maxn];
struct Edge
{
    int from,to,next,val;
}edge[2*maxn];
inline void add_edge(int s,int e,int va)
{
    edge[cnt].from=s;
    edge[cnt].to=e;
    edge[cnt].next=head[s];
    edge[cnt].val=va;
    head[s]=cnt++;
}
inline void Init()
{
    cnt=0;
    for(int i=0;i<=n;i++)head[i]=-1;
}
void dfs(int cur,int fa,int va)
{
    down[cur][1]=a[cur];
    cost[cur]=va;
    for(int i=head[cur];i!=-1;i=edge[i].next)
    {
        int x=edge[i].to;
        if(x==fa)continue;
        dfs(x,cur,edge[i].val);
        if(down[x][1]-2*edge[i].val>=0)down[cur][1]+=down[x][1]-2*edge[i].val;
    }
}
void dfs1(int cur,int fa)
{
    down[cur][0]=a[cur];
    temp[cur]=max1[cur]=max2[cur]=0;
    for(int i=head[cur];i!=-1;i=edge[i].next)
    {
        int x=edge[i].to;
        if(x==fa)continue;
        dfs1(x,cur);
        if(down[x][0]-edge[i].val>0)
        {
            int t=down[cur][1];
            if(down[x][1]-2*edge[i].val>=0)t-=down[x][1]-2*edge[i].val;
            t+=down[x][0]-edge[i].val;
                if(t>=down[cur][0])
                {
                    max2[cur]=max1[cur];
                    temp[cur]=down[cur][0];
                    down[cur][0]=t;
                    max1[cur]=x;
                }
                else if(t>temp[cur])
                {
                    max2[cur]=x;
                    temp[cur]=t;
                }
        }
    }
}

void dfs2(int cur,int fa,int va)
{
    up[cur][1]=0;
    if(down[cur][1]-2*va>=0)up[cur][1]=max(up[cur][1],down[fa][1]-down[cur][1]+2*va+up[fa][1]-2*va);
    else up[cur][1]=max(up[cur][1],down[fa][1]+up[fa][1]-2*va);

    up[cur][0]=0;
    if(max1[fa]==cur)
    {
        int t=down[fa][0]-down[cur][0]+va;
        up[cur][0]=max(up[cur][0],t+up[fa][0]-va);
        int r=max2[fa];
        if(down[r][1]-2*cost[r]>0)t=t-down[r][1]+2*cost[r];
        t+=down[r][0]-cost[r];
        up[cur][0]=max(up[cur][0],t+up[fa][1]-va);
    }
    else 
    {

        int t=down[fa][0];
        if(down[cur][1]-2*va>0)t-=down[cur][1]-2*va;
        up[cur][0]=max(up[cur][0],t+up[fa][1]-va);
        t=down[fa][1];
        if(down[cur][1]-2*va>0)t-=down[cur][1]-2*va;
        up[cur][0]=max(up[cur][0],t+up[fa][0]-va);
    }
    for(int i=head[cur];i!=-1;i=edge[i].next)
    {
        int x=edge[i].to;
        if(x==fa)continue;
        dfs2(x,cur,edge[i].val);
    }
}

int main()
{
    int t,Case=0;
    read(t);
    while(t--)
    {
        read(n);Init();
        For(i,1,n)read(a[i]);
        int u,v,w;
        For(i,1,n-1)
        {
            read(u);read(v);read(w);
            add_edge(u,v,w);
            add_edge(v,u,w);
        }
        dfs(1,0,0);
        dfs1(1,0);
        dfs2(1,0,0);
        printf("Case #%d:
",++Case);
        for(int i=1;i<=n;i++)printf("%d
",max(down[i][0]+up[i][1],down[i][1]+up[i][0]));
    }    
    return 0;
}

  

原文地址:https://www.cnblogs.com/zhangchengc919/p/5856654.html