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<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<vector> #include <math.h> #include<queue> #define ll long long #define met(a,b) memset(a,b,sizeof(a)); #define N 10010 using namespace std; struct node { int u,v,next; }Map[N<<2]; int k; int s[N],vis[N],a[N]; void add(int u,int v) { Map[k].u=u; Map[k].v=v; Map[k].next=a[u]; a[u]=k++; } int dfs(int h) { int sum=0; vis[h]=1; for(int i=a[h];i!=-1;i=Map[i].next) { int v=Map[i].v; if(!vis[v]) { vis[v]=1; sum+=dfs(v); } } return max(s[h],sum); } int main() { int t,n,m,e,f; scanf("%d",&t); while(t--) { scanf("%d %d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&s[i]); k=0; met(a,-1); for(int i=1;i<n;i++) { scanf("%d %d",&e,&f); add(e,f); add(f,e); } met(vis,0); printf("%d\n",dfs(m)); } return 0; }
时间: 2024-11-01 19:31:53