\(\mathtt{Problem H}\) \(\mathtt{Monster}\) \(\mathtt{Hunter}\)

\(\mathcal{Description}\)

题目

给定一棵 \(n\)\((n \leq 10^6)\) 个点的树,除 \(1\) 号结点外每个结点都有一只怪兽,打败他需要先消耗 \(a_i\) 点 \(HP\),击败后可以获得 \(b_i\) 点 \(HP\),求打败所有怪兽需要的最小 \(HP\)。

\(\mathcal{Solution}\)

先不考虑父亲的限制关系,考虑最优攻击顺序。

  • 对于 \(a_i < b_i\) \(a_j < b_j\) 的怪兽,那 \(a\) 小的优先。
  • 对于 \(a_i \geq b_i\) \(a_j < b_j\) 的怪兽,那优先 \(a < b\) 的。
  • 对于 \(a_i > b_i\) \(a_j > b_j\) 的怪兽,那 \(b\) 大的优先。

然后再来考虑父亲的限制,对于每个儿子,如果他的优先级大于他的父亲的优先级,那我们可以把他并到他的父亲节点上,假设下次的优先级最高的是兼并后的父节点,相当于先干掉了优先级更高的子节点而后干掉父节点。

\(\mathcal{Code}\)

#include<bits/stdc++.h>
using namespace std; const int N = 1e5 + 5; struct Node {
long long a, b;
int id;
bool operator <(const Node &x) const {
if (b > a && x.b > x.a)
return a > x.a;
if (b <= a && x.b > x.a)
return true;
if (b <= a && x.b <= x.a)
return x.b > b;
if (b >= a && x.b <= x.a)
return false;
}
} a[N]; priority_queue<Node> q;
vector <int> edge[N];
int fa1[N], fa[N], n; inline int read() {
int x = 0, k = 1; char c = getchar();
for (; c < 48 || c > 57; c = getchar()) k ^= (c == '-');
for (; c >= 48 && c <= 57; c = getchar()) x = x * 10 + (c ^ 48);
return k ? x : -x;
} inline long long read1() {
long long x = 0, k = 1; char c = getchar();
for (; c < 48 || c > 57; c = getchar()) k ^= (c == '-');
for (; c >= 48 && c <= 57; c = getchar()) x = x * 10 + (c ^ 48);
return k ? x : -x;
} void dfs(int x, int fa) {
fa1[x] = fa;
int sz = edge[x].size();
for (int i = 0; i < sz; i++) {
int y = edge[x][i];
if (y == fa)
continue;
dfs(y, x);
}
} int find(int x) {
return (fa[x] == x) ? x : (fa[x] = find(fa[x]));
} inline Node Merge(Node a, Node b) {
return (Node)
{a.a + std::max(0ll, - a.b + b.a),
b.b + std::max(0ll, a.b - b.a)};
} int main() {
n = read();
for (int i = 1; i <= n; i++)
fa[i] = i;
a[1] = (Node) {0, 0, 1};
for (int i = 2; i <= n; i++)
a[i] = (Node) {read1(), read1(), i};
for (int i = 1; i < n; i++) {
int x = read(), y = read();
edge[x].push_back(y);
edge[y].push_back(x);
}
dfs(1, 1);
for (int i = 2; i <= n; i++)
q.push(a[i]);
while (!q.empty()) {
Node t = q.top();
q.pop();
if (t.id == 1) continue; // root
if (a[t.id].a != t.a || a[t.id].b != t.b)
continue; // Merge
int Fa = find(fa1[t.id]);
fa[t.id] = Fa;
// Node &tt = a[Fa];
a[Fa] = Merge(a[Fa], a[t.id]);
a[Fa].id = Fa;
q.push(a[Fa]);
}
printf("%lld\n", a[1].a);
return 0;
}

最新文章

  1. Microsoft 家族新成员 Datazen 移动BI 介绍
  2. Max批量导出工具
  3. hdu 5927 Auxiliary Set 贪心
  4. 调用WCF Data Service的几点Tips
  5. How to say &quot;no&quot;?
  6. HDU 5127 Dogs&#39; Candies
  7. Gridview点击Edit编辑未update和cancel后的问题
  8. hpuoj 问题 A: 做不出来踢协会!!!
  9. 遗传算法Matlab源程序
  10. Atitit.dwr3 不能显示错误具体信息的解决方式,控件显示错误具体信息的解决方式 java .net php
  11. poj1947(树形dp)
  12. 转:java泛型
  13. iOS .tbd
  14. Fedora 23+CUDA 8.0+ GTX970 安装
  15. robot framework中的timeout的关键词
  16. python 打印 emoji
  17. leecode第二十一题(合并两个有序链表)
  18. 利用sql语句进行增删改查
  19. HanLP分词命名实体提取详解
  20. IOS初级:NSKeyedArchiver

热门文章

  1. centos 升级python
  2. k8s-mysql搭建
  3. postgres服务相关语法
  4. 在Anaconda环境下使用Jupyter Notebook
  5. Delphi ini文件操作 TIniFile、TMemIniFile
  6. 四轴电池ADC监控学习
  7. Codeforces Round #420 (Div. 2) E. Okabe and El Psy Kongroo dp+矩阵快速幂
  8. echarts 柱状图 X(Y)轴数据过多时,滑动以及内置缩放的问题
  9. 2019 ICPC Asia Nanchang Regional C And and Pair 找规律/位运算/dp
  10. Mac Office2016 安装及破解