P9847 [ICPC2021 Nanjing R] Crystalfly 题解
Brilliant11001 · · 题解
题目传送门
更好的阅读体验
甘雨可爱捏
题目大意:
给定一棵有
数据范围:
思路:
很明显是树形 dp。
从条件
有多快?假如当前走到一个节点
所以可以分析出几种行走方式:
- 走到节点
i ,然后走到它的某个子节点处,其他子节点全部飞走; - 走到节点
i ,然后走到它的某个子节点v_1 处,立即返回,走到另一个t = 3 的子节点v_2 处,其余子节点全部飞走,v_1 的子节点也全部飞走。
根据以上分析,我们可以设计出两种状态:
设
#include <vector>
#include <iostream>
using namespace std;
const int N = 100010;
typedef long long ll;
typedef pair<ll, int> PLI;
const ll inf = 0x3f3f3f3f3f3f3f3f;
int T, n;
vector<int> e[N];
int a[N], t[N];
ll f[N][2];
void dfs(int u, int fa) {
ll sum = 0;
int maxx = 0;
for(auto v : e[u]) if(v != fa) {
dfs(v, u);
sum += f[v][0];
maxx = max(maxx, a[v]);
}
f[u][0] = sum + maxx;
//以上是走法一
PLI maxx1 = {-inf, 0}, maxx2 ={-inf, 0};
for(auto v : e[u]) if(v != fa && t[v] == 3) {
PLI now = {a[v], v};
if(maxx2 < now) maxx2 = now;
if(maxx1 < maxx2) swap(maxx1, maxx2);
}
//以上是预处理最大值和次大值
for(auto v : e[u]) if(v != fa) {
ll tmp = sum + f[v][1] - f[v][0];
if(v == maxx1.second) tmp += maxx2.first;
else tmp += maxx1.first;
f[u][0] = max(f[u][0], tmp);
}
//以上是走法二
f[u][1] = sum + a[u];
}
void solve() {
for(int i = 1; i <= n; i++) e[i].clear();
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
for(int i = 1; i <= n; i++) scanf("%d", &t[i]);
for(int i = 1, a, b; i < n; i++) {
scanf("%d%d", &a, &b);
e[a].push_back(b);
e[b].push_back(a);
}
dfs(1, -1);
printf("%lld\n", f[1][0] + a[1]);
}
int main() {
scanf("%d", &T);
while(T--) {
solve();
}
return 0;
}