P9847 [ICPC2021 Nanjing R] Crystalfly 题解 (SPJ)

ICPC2021 Nanjing R Crystalfly

传送门?

题面翻译

给定一个 n ( 1 ≤ n ≤ 1 0 5 ) n(1\le n\le10^5) n(1≤n≤105) 个节点的树,每个节点上有 a i a_i ai 只晶蝶。派蒙最初在 1 1 1 号节点,并获得 1 1 1 号节点的所有晶蝶,接下来每一秒她可以移动到相邻的节点上并获得节点上的所有晶蝶,但是当她每到达一个节点 u u u 后,对于每个与 u u u 相邻的节点 v v v,节点 v v v 上的的晶蝶会在 t v ( 1 ≤ t v ≤ 3 ) t_v(1\le t_v\le3) tv(1≤tv≤3) 秒内消失,在 t v t_v tv 秒后再到达节点 v v v 将无法获得节点上的晶蝶。现在需要你求出最多可以获得的晶蝶数。

题目描述

Paimon is catching crystalflies on a tree, which are a special kind of butterflies in Teyvat. A tree is a connected graph consisting of n n n vertices and ( n − 1 ) (n - 1) (n−1) undirected edges.

There are initially a i a_i ai crystalflies on the i i i-th vertex. When Paimon reaches a vertex, she can catch all the remaining crystalflies on the vertex immediately. However, the crystalflies are timid. When Paimon reaches a vertex, all the crystalflies on the adjacent vertices will be disturbed. For the i i i-th vertex, if the crystalflies on the vertex are disturbed for the first time at the beginning of the t ′ t' t′-th second, they will disappear at the end of the ( t ′ + t i ) (t' + t_{i}) (t′+ti)-th second.

At the beginning of the 0 0 0-th second, Paimon reaches vertex 1 1 1 and stays there before the beginning of the 1 1 1-st second. Then at the beginning of each following second, she can choose one of the two operations:

  • Move to one of the adjacent vertices of her current vertex and stay there before the beginning of the next second (if the crystalflies in the destination will disappear at the end of that second she can still catch them).
  • Stay still in her current vertex before the beginning of the next second.

Calculate the maximum number of crystalflies Paimon can catch in 1 0 1 0 1 0 1 0 10 10^{10^{10^{10^{10}}}} 1010101010 seconds.

输入格式

There are multiple test cases. The first line of the input contains an integer T T T indicating the number of test cases. For each test case:

The first line contains an integer n n n ( 1 ≤ n ≤ 1 0 5 1 \le n \le 10^5 1≤n≤105) indicating the number of vertices.

The second line contains n n n integers a 1 , a 2 , ⋯   , a n a_1, a_2, \cdots, a_n a1,a2,⋯,an ( 1 ≤ a i ≤ 1 0 9 1 \le a_i \le 10^9 1≤ai≤109) where a i a_i ai is the number of crystalflies on the i i i-th vertex.

The third line contains n n n integers t 1 , t 2 , ⋯   , t n t_1, t_2, \cdots, t_n t1,t2,⋯,tn ( 1 ≤ t i ≤ 3 1 \le t_i \le 3 1≤ti≤3) where t i t_i ti is the time before the crystalflies on the i i i-th vertex disappear after disturbed.

For the next ( n − 1 ) (n - 1) (n−1) lines, the i i i-th line contains two integers u i u_i ui and v i v_i vi ( 1 ≤ u i , v i ≤ n 1 \le u_i, v_i \le n 1≤ui,vi≤n) indicating an edge connecting vertices u i u_i ui and v i v_i vi in the tree.

It's guaranteed that the sum of n n n of all the test cases will not exceed 1 0 6 10^6 106.

输出格式

For each test case output one line containing one integer indicating the maximum number of crystalflies Paimon can catch.

样例 #1

样例输入 #1

复制代码
2
5
1 10 100 1000 10000
1 2 1 1 1
1 2
1 3
2 4
2 5
5
1 10 100 1000 10000
1 3 1 1 1
1 2
1 3
2 4
2 5

样例输出 #1

复制代码
10101
10111

提示

For the first sample test case, follow the strategy below.

  • During the 0 0 0-th second
    • Paimon arrives at vertex 1 1 1;
    • Paimon catches 1 1 1 crystalfly;
    • Crystalflies in vertices 2 2 2 and 3 3 3 are disturbed.
  • During the 1 1 1-st second
    • Paimon arrives at vertex 3 3 3;
    • Paimon catches 100 100 100 crystalflies.
  • During the 2 2 2-nd second
    • Paimon arrives at vertex 1 1 1;
    • Crystalflies in vertex 2 2 2 disappears.
  • During the 3 3 3-rd second
    • Paimon arrives at vertex 2 2 2;
    • Crystalflies in vertices 4 4 4 and 5 5 5 are disturbed.
  • During the 4 4 4-th second
    • Paimon arrives at vertex 5 5 5;
    • Paimon catches 10000 10000 10000 crystalflies;
    • Crystalflies in vertex 4 4 4 disappears.

For the second sample test case, the optimal strategy is the same with the first sample test case. Crystalflies in vertex 2 2 2 are scheduled to disappear at the end of the 3 3 3-rd (instead of the 2 2 2-nd) second, allowing Paimon to catch them.

以上来自洛谷 以上来自洛谷 以上来自洛谷

解题思路

好好看题,就知道是树形 d p dp dp。定义 f u , 0 或 1 f_{u,0或1} fu,0或1 为遍历以 u u u 为根的整棵子树且 u u u 点的子节点的晶蝶消失( f u , 0 f_{u,0} fu,0)或不消失( f u , 1 f_{u,1} fu,1)的情况下所能获得的最大晶蝶数量。记与 u u u 相邻的非父亲节点中 t i = 3 t_i=3 ti=3 的节点晶蝶数量的最大值和第二大值分别为 m a x 1 , m a x 2 max1,max2 max1,max2,若不存在特判即可。

如果当前节点不存在 t i = 3 t_i=3 ti=3 的节点,则 f u , 0 = ( Σ f v , 1 ( v ∈ s o n u ) ) + m a x ( a v ) + f u , 1 = Σ f v , 1 ( v ∈ s o n u ) f_{u,0}=(\Sigma f_{v,1}(v\in son_u))+max(a_v)+f_{u,1}=\Sigma f_{v,1}(v\in son_u) fu,0=(Σfv,1(v∈sonu))+max(av)+fu,1=Σfv,1(v∈sonu)。

如果当前节点存在 t i = 3 t_i=3 ti=3 的节点,那么通过手动画图观察发现,记所有子节点的 f v , 1 f_{v,1} fv,1 的和 Σ f v , 1 ( v ∈ s o n u ) \Sigma f_{v,1}(v\in son_u) Σfv,1(v∈sonu)为 s u m sum sum, f u , 0 f_{u,0} fu,0 结果不变, f u , 1 = max ⁡ ⁡ ( f v , 0 + a v + s u m − f v , 1 + m a x 1 , f v , 0 + a v + s u m − f v , 1 + m a x 2 ) f_{u,1}=\max⁡(f_{v,0}+a_v+sum−f_{v,1}+max1,f_{v,0}+a_v+sum−f_{v,1}+max2) fu,1=max⁡(fv,0+av+sum−fv,1+max1,fv,0+av+sum−fv,1+max2)

最后的答案为 f 1 , 1 + a 1 f_{1,1}+a_1 f1,1+a1​。

AC Code

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int Maxn = 1e5 + 5;
vector<int> g[Maxn];
int n, u, v;
int a[Maxn];
int f[Maxn], sum[Maxn], t[Maxn];
inline void dfs(int u, int fa) {
	int maxx = 0;
	multiset<int> st;
	for (int v : g[u]) {
		if (v == fa) {
			continue;
		}
		dfs(v, u);
		sum[u] += f[v];
		maxx = max(maxx, a[v]);
		if (t[v] == 3) {
			st.insert(a[v]);
		}
	}
	f[u] = sum[u] + maxx;
	st.insert(LONG_LONG_MIN);
	for (int v : g[u]) {
		if (v == fa) {
			continue;
		}
		if (t[v] == 3) {
			st.erase(st.find(a[v]));
		}
		f[u] = max(f[u], sum[u] - f[v] + a[v] + sum[v] + *st.rbegin());
		if (t[v] == 3) {
			st.insert(a[v]);
		}
	}
}
inline void solve() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		g[i].clear();
		f[i] = sum[i] = 0;
	}
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	for (int i = 1; i <= n; i++) {
		cin >> t[i];
	}
	for (int i = 1; i <= n - 1; i++) {
		cin >> u >> v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	dfs(1, 0);
	cout << f[1] + a[1] << endl;
}
inline void work() {
	int T;
	cin >> T;
	while (T--) {
		solve();
	}
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	work();
	return 0;
}
相关推荐
z小猫不吃鱼8 分钟前
模型剪枝经典论文精读:Pruning Filters for Efficient ConvNets
算法·机器学习·剪枝
海清河晏11110 分钟前
数据结构 | 二叉搜索树
数据结构·c++·visual studio
盐焗鹌鹑蛋43 分钟前
【C++】继承
开发语言·c++
会周易的程序员1 小时前
使用 pybind11 封装 C++ 日志库 microLog 为 Python 模块
java·c++·python·物联网·架构·日志·aiot
WZF-Sang1 小时前
网络基础——2
服务器·网络·c++·学习·网络编程·php
czhaii1 小时前
串口1中断收发-C语言-MODBUS协议
c语言·开发语言
Fox爱分享2 小时前
字节二面:1000瓶酒,有一瓶是毒药,多少只老鼠可以查出来?
算法·面试·程序员
+wacyltd大模型备案算法备案2 小时前
大模型评估测试题库怎么建?风险分类、测试样本的完整方法
人工智能·算法·安全·分类·大模型·大模型备案·大模型上线登记
apihz2 小时前
随机驾考题目(C 照科一 / 科四 2000+ 题)免费API调用教程
android·java·c语言·开发语言·网络协议·tcp/ip
Fox爱分享2 小时前
字节二面智力题:100只老虎和1只羊关在一起,这只羊会不会被吃?
算法·面试·程序员