SGU 143.Long Live the Queen(女王*)

时间限制:0.25s

空间限制:4M

题意:

    有n(n<=16000)个小镇,每两个小镇有且仅有一条路径相连。每个小镇有一个收益x(-1000<=x<=1000).
    现在要求,选择一些小镇,满足下面两点要求:
    1.选择的小镇都能互相到达,并且路径上的小镇也被选择了.
    2.选择的小镇的收益和最大.

输入

   一个整数n,接下来n个整数,代表这n个小镇的收益.
   接下来n-1行,每行两个整数代表这两个小镇有道路直接相连.

输出

   一个整数,代表最大的收益

Sample Input

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

Sample Output

4

 

 

 

 


 

Solution:

                先来分析一下题目模型

             有一颗n(n<=16000)个节点的树,每个节点都有一个权值k(-1000<=k<=1000),

             求这颗树的一颗子树,使得子树的所有节点的权值和最大.

             假设已经选择了一些点,对于于他相邻的点,求出相邻点的连通块的和的最大值,如果这个值大于0,那么久把这个连通块加入选择.

             DFS即可.

参考代码:

 

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#define INf 16666
#define Maxn 0xfffffff
using namespace std;
vector<int> g[INf];
int val[INf], f[INf];
int n, x, y, tem;
int dfs (int x, int fa) {
	f[x] = val[x];
	for (int i = 0; i < g[x].size(); i++) {
              tem=0;
		if (g[x][i] != fa)
			tem = dfs (g[x][i], x);
		if (tem > 0) f[x] += tem;
	}
	return f[x];
}
int main() {
	scanf ("%d", &n);
	for (int i = 1; i <= n; i++) scanf ("%d", &val[i]);
	for (int i = 1; i < n; i++) {
		scanf ("%d %d", &x, &y);
		g[x].push_back (y);
		g[y].push_back (x);
	}
	dfs (1, -1);
	int ans = -Maxn;
	for (int i = 1; i <=n; i++)
		ans = max (ans, f[i]);
	printf ("%d", ans);
}

  

         

原文地址:https://www.cnblogs.com/keam37/p/3840422.html