洛谷 P5290 [十二省联考 2019] 春节十二响 解题报告
洛谷 P5290 [十二省联考 2019] 春节十二响 解题报告
题意
给定一些树上父子关系及各点权值,该树根为1号点。
将所有点划分成一些互不相交的集合,“集合”定义为__内部的点不能具有父子关系的集合__,“集合的价值”定义为__集合中的所有点的最大值__。
求所有集合的价值之和最小。
Solutions

如图为一棵以a为根节点的树,b、c、d、e分别为其四个儿子节点, b >= c >= d >= e。
由题意,应将根的任一子树同其他相同父亲的子树合并,即merge(son[fa] [x])。
所以合并a的左右子树,其中将b、c合并,又因为b >= c,所以c被抵消,保留b作为价值。
同理d、e合并,抵消较小的e,保留d作为价值。
因为a与自己的任一子节点都有瓜葛,所以它不和任何点合并,直接最后加入集合。
Proves
按照Sol方案,val_1 = max(b, c) + max(d, e) = b + d
反之,若b与e合并,则c只能与d合并。
则val_2 = max(b, e) + max(c, d) = b + c
因为b >= c >= d >= c
所以b + d >= b + c
所以val_1 <= val_2,即Sol方案更优。
因此可证每个点定和它对应子树的__同等大小级别的点__抵消,为最优解。
Details
-
根节点在子树合并完后最后加入集合,不和任何点合并抵消。
-
较大集合会有剩下的点,直接加入集合。
-
merge时 不能swap(x, y) ,而必须 swap(pq[x], pq[y]) ,否则会影响dfs中pq[x].push(a[x])加入集合。
-
时间复杂度证明:

每次合并耗费min(size_b, size_c)的时间复杂度(size_b、size_c为两个同级子树大小)。
一路合并上去,每合并后一颗树的size将缩减为其子树size的最大值,则近似为长链剖分的O(n)时间复杂度
再算上优先队列O(log(n)),则总时间复杂度O(n · log(n))。
不同于普通启发式合并不删只并,此题是删除了部分点后合并的,所以均摊合并两点时间复杂度O(1)。
Code
#include <bits/stdc++.h> using namespace std; inline int read() { int x = 0; char ch = getchar(); bool sgn = 0; while (ch < '0' || ch > '9') sgn |= ch == '-', ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + (ch & 15), ch = getchar(); return sgn ? -x : x; } const int MN = 2e5 + 10; int n, a[MN]; int cur, h[MN], nxt[MN], ver[MN]; vector<int> tmp; priority_queue<int> pq[MN]; long long ans; inline void add_edge(int x, int y) { cur++; ver[cur] = y, nxt[cur] = h[x], h[x] = cur; } inline void merge(int x, int y) { if (pq[x].size() < pq[y].size()) swap(pq[x], pq[y]); while (!pq[y].empty()) { tmp.push_back(max(pq[x].top(), pq[y].top())); pq[x].pop(), pq[y].pop(); } while (!tmp.empty()) pq[x].push(tmp.back()), tmp.pop_back(); } void dfs(int x) { for (int i = h[x]; i; i = nxt[i]) { int y = ver[i]; dfs(y), merge(x, y); } pq[x].push(a[x]); } signed main() { n = read(); for (int i = 1; i <= n; ++i) a[i] = read(); for (int i = 2, fa; i <= n; ++i) { fa = read(); add_edge(fa, i); } dfs(1); while (!pq[1].empty()) ans += pq[1].top(), pq[1].pop(); cout << ans << '\n'; return 0; }
Data
Code:https://www.luogu.com.cn/blog/xht37/p5290-shi-er-xing-lian-kao-2019-chun-jie-shi-er-xiang
思路 & 正确性证明:https://www.luogu.com.cn/blog/TheLostWeak/solution-p5290
时间复杂度证明:https://www.luogu.com.cn/blog/wufeiyang/solution-p5290
本文来自博客园,作者:zjsqwq,转载请注明原文链接:https://www.cnblogs.com/zjsqwq/p/16356723.html

浙公网安备 33010602011771号