题解:P16338 「ALFR Round 10」纸牌
可以看出,作为其他玩家,只要将
明显地,从
贪心地,让主人公尽量延后行动一定不劣。我们可以以
那就简单了,对于每个节点,维护它的子树中
最后不要忘记特判:如果
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int t, n, d;
int a[N], b[N];
int fa[N], mx[N], sz[N];
vector<int>e[N];
void make_tree(int s){
mx[s] = a[s];
sz[s] = 1;
for(int i : e[s]){
if(fa[i] == -1){
fa[i] = s;
make_tree(i);
mx[s] = max(mx[s], mx[i]);
sz[s] += sz[i];
}
}
// printf("node %d: mx %d, sz %d\n", s, mx[s], sz[s]);
}
signed main()
{
memset(fa, -1, sizeof fa);
cin >>t;
while(t--){
//清空
for(int i=1; i<=n; i++){
e[i].clear();
fa[i] = -1;
}
//输入
cin >>n >>d;
for(int i=1; i<=n; i++) cin >>a[i] >>b[i];
for(int i=1; i<n; i++){
int u, v;
cin >>u >>v;
e[u].push_back(v);
e[v].push_back(u);
}
//特判
if(b[d] > 2){
puts("0");
continue;
}
//建树并预处理
fa[d] = 0;
make_tree(d);
//答案
int ans = 0;
for(int son : e[d])
if(mx[son] >= a[d])
ans += sz[son];
cout <<ans <<endl;
}
return 0;
}
AC 记录