加入收藏 | 设为首页 | 会员中心 | 我要投稿 核心网 (https://www.hxwgxz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

hdu5834Magic boy Bi Luo with his excited tree(树形DP)

发布时间:2021-01-25 19:57:09 所属栏目:大数据 来源:网络整理
导读: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): 823????Accepted Submission(s): 222 Problem Description Bi Luo is a magic boy,he also has a mi

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): 823????Accepted Submission(s): 222


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(T≤104) ?,represents there are? T ?test cases.

Four each test:

The first line contain an integer? N (N≤105) .

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

For the next? N?1 ?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(1≤c≤104) .

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
  
  
? 这道题的题意就是给你一个树,每一个节点有一个收益,每条边每次经过都会有一个花费。问你从每个节点出发,最大的收益是多少。 这道题就是一个很明显的树形DP了,两个dfs,一个dfs是更新每个节点从当前节点出发回到原点的最大收益和不回到原点的最大收益,以及到达的位置。 第二个dfs是从父节点向下更新每个节点的答案。这个还是不难想的,就是细节有点多写起来有些烦。 AC代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=1e5+5;
int head[maxn],tot,val[maxn];
int w[maxn],bw[maxn],wid[maxn],ans[maxn];
/*
	w表示当前回来的最大收益 
	bw表示当前走出去的最大收益 
	id表示做出去的最大收益的节点 
*/
void init(){
	memset(head,-1,sizeof(head));
	tot=0;
}
struct Edge{
	int from,to,next,cost;
	Edge(){}
	Edge(int from,int to,int cost,int next){
		this->from=from;
		this->to=to;
		this->cost=cost;
		this->next=next;
	}
}e[maxn*2];
void add_edge(int u,int v,int c){
	e[tot]=Edge(u,v,c,head[u]);
	head[u]=tot++;
	e[tot]=Edge(v,u,head[v]);
	head[v]=tot++;
}
void dfs1(int u,int fa){
	w[u]=val[u];
	bw[u]=val[u];
	wid[u]=0;
	for(int i=head[u];~i;i=e[i].next){
		int v=e[i].to;
		if(v==fa)	continue;
		dfs1(v,u);
		int btemp=max(0,bw[v]-e[i].cost*2);//回来的收益 
		int temp=bw[u]+max(0,w[v]-e[i].cost);//不回来的收益 
		w[u]+=btemp;
		bw[u]+=btemp;
		if(w[u]<temp){
			w[u]=temp;
			wid[u]=v;
		}		
	}
}
void dfs2(int u,int fa,int sum1,int sum2){
//sum1表示当前节点不回来的最大收益,sum2表示当前节点回来的最大收益 
	ans[u]=max(w[u]+sum2,bw[u]+sum1);
	int W=w[u];
	int BW=bw[u];
	int Id=wid[u];
	W+=sum2;	
	if(W<=BW+sum1){
		W=BW+sum1;
		Id=fa;
	}
	BW+=sum2;
	for(int i=head[u];~i;i=e[i].next){
		int v=e[i].to;
		if(v==fa) continue;
		if(v==Id){
			int tmp1=sum1+val[u],tmp2=sum2+val[u];
			for(int j=head[u];~j;j=e[j].next){
				int vv=e[j].to;
				if(vv==fa || v==vv)	continue;
				int tmp=max(0,bw[vv]-e[j].cost*2);
				tmp1=max(tmp2+max(0,w[vv]-e[j].cost),tmp1+tmp);
				tmp2+=tmp;
			}
			tmp1=max(0,tmp1-e[i].cost);
			tmp2=max(0,tmp2-2*e[i].cost);
			dfs2(v,tmp1,tmp2);
		}
		else{
			int tmp=max(0,bw[v]-e[i].cost*2);
			int tmp1=max(0,W-tmp-e[i].cost);
			int tmp2=max(0,BW-tmp-e[i].cost*2);
			dfs2(v,tmp2);
		}
	}
}
int main(){
	int n,t,icas=1;
	scanf("%d",&t);
	while(t--){
		init();
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
			scanf("%d",&val[i]);
		for(int i=1;i<n;i++){
			int u,c;
			scanf("%d%d%d",&u,&v,&c);
			add_edge(u,c);
		}
		dfs1(1,-1);
		dfs2(1,0);
		printf("Case #%d:n",icas++);
        for(int i = 1; i <= n; ++i)
            printf("%dn",ans[i]);
	}
}

(编辑:核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读