传送门:QAQ
题意:给你一棵树,每条边有权值,然后会给你几个带有权值的机器人从根节点出发,机器人会选择小于等于自己权值的最大的一条边,最后它会停在一个点上。问你所有机器人到达的点的和是多少。
思路:只要深搜即可,因为按权值降序的机器人选择的点符合dfs序,只要在dfs时判断当前点是否能停下即可,否则就是dfs序的下一个点。
代码:
#include<iostream>
#include<math.h>
#include<stdlib.h>
#include<cstring>
#include<queue>
#include<vector>
#include<cstdio>
#include<utility>
#include<algorithm>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
int n, q;
struct inst {
int v;
int w;
};
ll sum;
vector<inst>gx[100010];
int maxx[100010];
priority_queue<int>qq;
int cmp(inst a, inst b) {
return a.w > b.w;
}
void dfs(int x, int pre) {
int minn = inf;
for (int i = 0; i < gx[x].size(); i++) {
if (gx[x][i].v == pre) continue;
else {
maxx[gx[x][i].v] = max(maxx[x], gx[x][i].w);
if (qq.top()>gx[x][i].w) {
dfs(gx[x][i].v, x);
}
else
continue;
}
}
if (qq.empty()) return;
while (!qq.empty()&&qq.top()>maxx[x]) {
sum += x;
//printf("%d\n", x);
qq.pop();
}
}
void work() {
dfs(1, -1);
}
int main(void) {
int t;
scanf("%d", &t);
while (t--) {
memset(maxx, 0, sizeof(maxx));
scanf("%d%d", &n, &q);
for (int i = 0; i <= n; i++) {
gx[i].clear();
}
while (!qq.empty())
qq.pop();
sum = 0;
for (int i = 0; i < n - 1; i++) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
inst cc;
cc.v = b;
cc.w = c;
gx[a].push_back(cc);
cc.v = a;
gx[b].push_back(cc);
}
for (int i = 1; i <= n; i++) {
sort(gx[i].begin(), gx[i].end(), cmp);
}
for (int i = 0; i < q; i++) {
int yy;
scanf("%d", &yy);
qq.push(yy);
}
work();
printf("%lld\n", sum);
}
}