HDU 6326 Problem H Monster Hunter

\(\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;
}

原文地址:https://www.cnblogs.com/wjnclln/p/11683290.html

时间: 2024-11-08 22:53:52

HDU 6326 Problem H Monster Hunter的相关文章

HDU 4910 Problem about GCD

Problem about GCD Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 470    Accepted Submission(s): 77 Problem Description Given integer m. Find multiplication of all 1<=a<=m such gcd(a, m)=1 (cop

HDU 2616 Kill the monster (暴力搜索 || 终极暴力全排列)

题目链接:HDU 2616 Kill the monster 题意:有N个技能去打HP有M的怪兽,技能(A,M),技能伤害为A,当怪兽HP<=M时伤害为2*A.求打死怪兽(HP<=0)用的最少技能 方法一:将技能全排列,计算伤害,得到答案. 方法二:搜索,具体看代码. 全排列AC代码: #include<stdio.h> #include<algorithm> using namespace std; struct node { int p,v; }; struct n

HDU 2256 Problem of Precision (矩阵快速幂)

HDU 2256 Problem of Precision (矩阵快速幂) ACM 题目地址:HDU 2256 Problem of Precision 题意: 给出一个式子,求值. 分析: 推起来最后那步会比较难想. 具体过程见: 表示共轭只听说过复数的和图的... 这构题痕迹好明显... 跟基友开玩笑说:如果遇到这种题,推到Xn+Yn*sqrt(6)这步时,打表最多只能打到10就爆int了,这是输出正解和Xn,说不定眼神好能发现ans = Xn * 2 - 1呢.= =... 代码: /*

hdu 4910 Problem about GCD(数论)

题目连接:hdu 4910 Problem about GCD 题目大意:给定M,判断所有小于M并且和M互质的数的积取模M的值. 解题思路:有个数论的结论,若为偶数,M=M/2. 可以写成M=pk,即只有一种质因子时,答案为M-1,否则为1.特殊情况为4的倍数,不包括4. 首先用1e6以内的素数去试除,如果都不可以为p,那么对大于1e6的情况判断一下是否为素数,是素数也可以(k=1),否则开方计算,因为M最大为1e18,不可能包含3个大于1e6的质因子. #include <cstdio> #

HDU 4910 Problem about GCD(米勒拉宾)

HDU 4910 Problem about GCD 题目链接 题意:给定一个数字,求出1 - n之间与他互质的数的乘积mod n 思路:看了网上别人找出来的规律,原文链接 然后由于这题的n很大,也没法直接判定,可以这样搞,先去试10^6以内的素数,判断可不可以,如果不行,再利用米勒拉宾判下是否是素数,如果不是的话,把这个数字开根在平方,判断是不是完全平方数,这样做的原因是数字最大10^18,如果没有10^6以内的质因子,又不是质数的话,那么他最多只能包含2个质因子了,那么如果他不是一个完全平方

Problem H. The Fence

/** 题目:Problem H. The Fence 链接:https://vjudge.net/problem/Gym-101090H 题意:给定一个字符串,只有0或者1: 问:假如两个不同的1之间的0,1数量是k的倍数(包括0倍)则输出这两个1的位置: 思路:%k:直到遇到两个相同的余数,说明之间的01数量为k的倍数. */ #include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1

Codeforces Gym 100610 Problem H. Horrible Truth 瞎搞

Problem H. Horrible Truth Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100610 Description In a Famous TV Show “Find Out” there are n characters and only one Horrible Truth. To make the series breathtaking all way long, the sc

hdu String Problem(最小表示法入门题)

hdu 3374 String Problem 最小表示法 view code#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <string> using namespace std; const int N = 10010; int n; char s[105]; map<

Moscow Subregional 2010 Problem H. Hometask 转化、素数筛选

ACM ICPC 2010-2011 NEERC Moscow Subregional Contest Moscow, October 24, 2010 Problem H. Hometask Time limit: 1 second Memory limit: 256 megabytes Kolya is still trying to pass a test on Numbers Theory. The lecturer is so desperate about Kolya's knowl