The tree of life (search, the root of the tree turns into a root) Blue Bridge Cup Provincial Championship

Topic description

In the X forest, God created the tree of life.

He marked each node (the leaf is also called a node) of each tree with an integer representing the harmony value of this point.
God wants to select a non-empty node set S in this tree, so that for any two points a, b in S, there is a point column {a, v1, v2, ..., vk, b} such that this point Each point in the column is an element in S, and there is an edge between two adjacent points in the sequence.

Under this premise, God wants to make the sum of the integers corresponding to the points in S as large as possible.
This greatest sum is God's score for the tree of life.

After atm's efforts, he already knew the integers that God gave to every node on every tree. But since the atm is not good at calculations, he doesn't know how to get the score efficiently. He needs you to write a program for him to calculate the score of a tree.

enter

An integer n in the first line indicates that the tree has n nodes.
The second line contains n integers, which in turn represent the score of each node.
Next n-1 lines, each line contains 2 integers u, v, indicating that there is an edge from u to v. Since this is a tree, there are no cycles.

output

Output a line with a number representing the score God gave the tree.

sample input

5
1 -2 -3 4 5
4 2
3 1
1 2
2 5

Sample output

8

First determine a root of the tree, and then search down from the root to determine whether to add the value of its subtree (when the sum of the subtree is positive, add it, because it contributes, otherwise it is not added) Because it is discussing the subtree, it must be are in the same set

The search uses the technique of rootless to rooted

#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
const int maxn = 1e6;
long long n,w[maxn],ww[maxn],ans;
vector<int> ve[maxn];//邻接表 
void dfs(int root,int fa){
    
    
	ww[root]=w[root];//初始化根 
	for(int i=0;i<ve[root].size();i++){
    
    //找出root所有的儿子 
		int son = ve[root][i];
		if(son!=fa){
    
    //这是无根转有根的技巧,防止反向搜索 
			dfs(son,root);
			if(ww[son]>0){
    
    //说明子树是正值,会有贡献 
				ww[root]+=ww[son];//加上子树的权值和 
			}
		}
		
	}
	if(ww[root]>ans)ans=ww[root];//任意一个节点都可以是最大权值和子树的根 
} 
int main(){
    
    
	cin>>n;
	for(int i=1;i<=n;i++){
    
    
		cin>>w[i];
	}
	for(int i=0;i<n-1;i++){
    
    
		int x,y;
		cin>>x>>y;
		ve[x].push_back(y);
		ve[y].push_back(x); 
	}
	//输入处理完毕
	 dfs(1,0);
	 cout<<ans<<endl;
	return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324944211&siteId=291194637