http://acm.zzuli.edu.cn/zzuliacm/problem.php?id=1907
Description 进去宝藏后, 小火山发现宝藏有N个房间,且这n个房间通过N-1道门联通。 每一个房间都有一个价值为Ai的宝藏, 但是每一个房间也都存在一个机关。如果小火山取走了这个房间的宝藏,那么这个房间通往其他房间的门就永远打不开了,也就是说后面的宝藏小火山是得不到了(进入这个房间的门是不会关闭的,小火山还是可以回去的);如果小火山不取这个宝藏,而是去打开通往另一房间的门,那么这个房间的宝藏就会消失, 小火山就得不到这个房间的宝藏。 不过,小火山已经有了藏宝图,知道每一个房间的宝藏的价值,现在想请你帮小火山算一下,他最多能获得多少钱去买股票? Input 输入第一行是一个整数T(T <= 50), 表示一共有T组数据。 对于每一组数据,第一行是两个数N, S(1 <= N <= 10000, 1 <= S <= N), N代表有N个房间, S代表小火山进去宝藏后的 起始房间(小火山怎么进入起始房间不重要),第二行是N个数,代表每个房间宝藏的价值, 随后N-1行, 每行两个数A, B, 代表 A, B这两个房间联通。 Output 对于每一组数据输出一个整数, 代表小火山能获得的最大钱数。 Sample Input 2 1 1 20 3 1 4 5 6 1 2 2 3 Sample Output 20 6
分析:一开始比较纠结到底要怎么处理取该房间宝藏其他房间门就关闭这一点。后来想通了。。
举例子来说,取一个点,把与之相邻的点的和加一起与这个点本身的值进行比较,哪个大取哪个即可。(简单的例子,与之相邻的点都没有其他相邻的点了)
若与之相邻的点还有其他的点,那么方法还是一样,按照这个方法进行递归即可。
#include <iostream> #include <stdio.h> #include <string.h> #include <string> #include <vector> #include <algorithm> #include <map> #include <queue> #include <stack> #include <math.h> using namespace std; #define met(a, b) memset(a, b, sizeof(a)) #define maxn 11000 #define INF 0x3f3f3f3f const int MOD = 1e9+7; typedef long long LL; int cnt, head[maxn], v[maxn], value[maxn]; struct node { int u, v, next; }maps[4*maxn]; void Add(int u, int v) { maps[cnt].v = v; maps[cnt].next = head[u]; head[u] = cnt ++; } int DFS(int s) { int sum = 0; for(int i=head[s]; i!=-1; i=maps[i].next) { int p = maps[i].v; if(!v[p]) { v[p] = 1; sum += DFS(p); } } return max(sum, value[s]); } int main() { int T, a, b, s, n; scanf("%d", &T); while(T --) { scanf("%d %d", &n, &s); for(int i=1; i<=n; i++) scanf("%d", &value[i]); memset(head, -1, sizeof(head)); cnt = 0; for(int i=1; i<n; i++) { scanf("%d %d", &a, &b); Add(a, b); Add(b, a); } memset(v, 0, sizeof(v)); v[s] = 1; int ans = DFS(s); printf("%d ", max(ans, value[s])); } return 0; } /* 1 5 2 5 5 2 1 5 1 5 1 2 2 3 2 4 */