题目链接: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 21 1 20 3 1 4 5 6 1 2 2 3 Sample Output 20 6 HINT Source
analyse:
进入一个房间后有两种选择:
1>拿走此房间宝藏,后面的不要了;
2>此房间宝藏放弃,拿走与此房间相连的所有其他房间的宝藏;
#include <cstdio> #include <cstring> #include <iostream> #include <cmath> #include<vector> #include<queue> #include<algorithm> using namespace std; typedef long long LL; const int maxn=50009; const int INF=0x3f3f3f3f; const int mod=2009; int head[maxn]; int value[maxn]; int vis[maxn]; int n, k; struct node { int v, next; } maps[maxn<<2]; void Add(int u, int v) { maps[k].v=v; maps[k].next=head[u]; head[u]=k++; } int DFS(int s) { int sum=0; for(int i=head[s]; i!=-1; i=maps[i].next) { int v=maps[i].v; if(!vis[v]) { vis[v]=1; sum+=DFS(v); } } return max(sum, value[s]); } int main() { int T, s; 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)); k=0; for(int i=1; i<n; i++) { int a, b; scanf("%d %d", &a, &b); Add(a, b); Add(b, a); } memset(vis, 0, sizeof(vis)); vis[s]=1; int ans=DFS(s); printf("%d\n", max(ans, value[s])); } return 0; }
时间: 2024-10-12 14:46:45