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);

}

 

  

         

 

你可能感兴趣的:(long)