Hdu-5834 Magic boy Bi Luo with his excited tree(树形DP)

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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define INF 0x3f3f3f3f
#define eps 1e-9
#define MAXN 100005
using namespace std;
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}  
struct thing
{
	int v,value;
	thing(int a,int b)
	{
		v = a,value = b;
	}
};
vector  G[MAXN];
int T,n,f[MAXN][2],cho[MAXN],bac[MAXN],nbac[MAXN],snbac[MAXN],val[MAXN],Fa[MAXN],faval[MAXN],ans[MAXN],up[MAXN][2];
void dfs(int u,int fa)
{
	Fa[u] = fa;
	int child = 0;
	for(thing v : G[u])
	if(v.v != fa) dfs(v.v,u);
	else faval[u] = v.value;
	for(thing v : G[u])
	 if(v.v != fa) 
	 {
	 	child++;
	 	int Val = v.value;
	    if(f[child-1][1] + max(0,nbac[v.v] - Val) > f[child-1][0] + max(0,bac[v.v]- 2*Val))
	 	{
	 		f[child][0] = f[child-1][1] + max(0,nbac[v.v] - Val);
	 		cho[u] = v.v;
 		}			
 		else f[child][0] = f[child-1][0] + max(0,bac[v.v]- 2*Val);
		f[child][1] = f[child-1][1] + max(0,bac[v.v] - 2*Val);		
	}
	if(!child) bac[u] = nbac[u] = max(0,val[u]);
	else 
	{
		bac[u] = val[u] + f[child][1];
		nbac[u] = val[u] + f[child][0];
	}
	child = 0;
	for(thing v : G[u])
	 if(v.v != fa) 
	 {
	 	child++;
	 	int Val = v.value;
	 	if(f[child-1][1] + max(0,nbac[v.v] - Val) > f[child-1][0] + max(0,bac[v.v]- 2*Val) && v.v != cho[u])
	 	{
	 		f[child][0] = f[child-1][1] + max(0,nbac[v.v] - Val);
	 	}
 		else f[child][0] = f[child-1][0] + max(0,bac[v.v]- 2*Val);
	}
	snbac[u] = val[u] + f[child][0];
}
void dfs2(int u,int fa)
{
	if(fa > 0)
	{
		int f0,f1;
		if(u != cho[fa]) f0 = nbac[fa] - max(0,bac[u] - 2*faval[u]);
		else f0 = snbac[fa] - max(0,bac[u] - 2*faval[u]);
		f1 = bac[fa] - max(0,bac[u] - 2*faval[u]);
		if(Fa[fa] > 0)
		{
			f0 = max(f0 + max(0,up[fa][1]),f1 + max(0,up[fa][0]));
			f1 += max(0,up[fa][1]);
		} 
		up[u][0] = max(0,f0 - faval[u]);
		up[u][1] = max(0,f1 - 2*faval[u]);
		ans[u] = max(max(up[u][1],0)+max(0,nbac[u]),max(up[u][0],0)+max(0,bac[u])); 
	}
	else ans[u] = nbac[u];
	for(thing v : G[u])
	 if(v.v != fa) dfs2(v.v,u);
}
int main()
{
	T = read();
	for(int t = 1;t <= T;t++)
	{
		n = read();
		for(int i = 1;i <= n;i++)
		{
			val[i] = read();
			G[i].clear();
		}
		for(int i = 1;i < n;i++)
		{
			int u,v,Val;
			u = read(),v = read(),Val = read();
			G[u].push_back(thing(v,Val));
			G[v].push_back(thing(u,Val));
		}
		dfs(1,-1);
		dfs2(1,-1);
		printf("Case #%d:\n",t);
		for(int i = 1;i <= n;i++) printf("%d\n",ans[i]);
	}
}


你可能感兴趣的:(ACM,DP动态规划)