HDU 6326 Problem H. Monster Hunter (贪心+并查集)*

本篇介绍了一款名为“MonsterHunter”的游戏挑战问题。玩家需要在有限时间内清除所有怪物以获胜,通过计算最小初始生命值确保游戏过程中生命值始终为正。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

Problem H. Monster Hunter

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 773    Accepted Submission(s): 194


 

Problem Description

Little Q is fighting against scary monsters in the game ``Monster Hunter''. The battlefield consists of n intersections, labeled by 1,2,...,n , connected by n−1 bidirectional roads. Little Q is now at the 1 -th intersection, with X units of health point(HP).
There is a monster at each intersection except 1 . When Little Q moves to the k -th intersection, he must battle with the monster at the k -th intersection. During the battle, he will lose ai units of HP. And when he finally beats the monster, he will be awarded bi units of HP. Note that when HP becomes negative(<0 ), the game will over, so never let this happen. There is no need to have a battle at the same intersection twice because monsters do not have extra life.
When all monsters are cleared, Little Q will win the game. Please write a program to compute the minimum initial HP that can lead to victory.

 

 

Input

The first line of the input contains an integer T(1≤T≤2000) , denoting the number of test cases.
In each test case, there is one integer n(2≤n≤100000) in the first line, denoting the number of intersections.
For the next n−1 lines, each line contains two integers ai,bi(0≤ai,bi≤109) , describing monsters at the 2,3,...,n -th intersection.
For the next n−1 lines, each line contains two integers u and v , denoting a bidirectional road between the u -th intersection and the v -th intersection.
It is guaranteed that ∑n≤106 .

 

 

 

Output

For each test case, print a single line containing an integer, denoting the minimum initial HP.

 

 

Sample Input

 

1 4 2 6 5 4 6 2 1 2 2 3 3 4

 

 

Sample Output

 

3

 

 

Source

2018 Multi-University Training Contest 3

 

 

Recommend

chendu   |   We have carefully selected several similar problems for you:  6361 6360 6359 6358 6357 

#include<iostream>
#include<algorithm>
#include<string>
#include<map>//int dx[4]={0,0,-1,1};int dy[4]={-1,1,0,0};
#include<set>//int gcd(int a,int b){return b?gcd(b,a%b):a;}
#include<vector>
#include<cmath>
#include<queue>
#include<string.h>
#include<stdlib.h>
#include<cstdio>
#define mod 1e9+7
#define ll long long
#define MAX 1000000000
#define ms memset
using namespace std;
const int maxn=1e5+5;
/*
题目大意:一颗树,每个怪兽有a和b属性,
先减去a再加上b,
如果不是树形那么这题就好办了,
但关键是要先打下父节点才能打子节点。

用并查集来代替这个结构,
再用优先队列把点压入并拟定优先级。
这样按顺序更新父节点即可。

*/

int n;
struct node
{
    ll a,b, id;
    node(){}
    bool operator<(const node &x) const
    {

        if (b-a>=0&&x.b-x.a<0) return false;

        if (b-a<0&&x.b-x.a>=0) return true;

        return b-a>0?a>x.a:b<x.b;
    }
    bool operator!=(const node& y) const
    {
        return a!=y.a||b!=y.b;
    }
};
node s[maxn];///点集合

int fa[maxn],f[maxn];///用dfs来补充fa。
int Find(int x) { return x==f[x]?x:f[x]=Find(f[x]); }

priority_queue<node> pq;
vector<int> sons[maxn];

void dfs(int u,int v)
{
    for(int i=0;i<sons[u].size();i++)
    {
        int p=sons[u][i];
        if(p==v) continue;
        fa[p]=u;dfs(p,u);
    }
}

int main()
{
    int t;scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);

        for(int i=1;i<=n;i++) sons[i].clear();

        s[1].a=s[1].b=0,s[1].id=1;
        fa[1]=f[1]=1;

        for(int i=2;i<=n;i++)
        {
            scanf("%lld%lld",&s[i].a,&s[i].b);
            s[i].id=f[i]=i;
            pq.push(s[i]);
        }

        for(int i=0;i<n-1;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            sons[x].push_back(y);
            sons[y].push_back(x);
        }

        dfs(1,0);

        while(!pq.empty())
        {
            int x=pq.top().id;
            if(pq.top()!=s[x]||x==1) { pq.pop();continue; }///已经被修改过的点就不用单独修改了
            int y=Find(fa[x]); f[x]=y; pq.pop();
            s[y].a+=max(0ll,s[x].a-s[y].b);
            s[y].b=s[x].b+max(0ll,s[y].b-s[x].a);
            pq.push(s[y]);
        }
        printf("%lld\n",s[1].a);
    }
    return 0;
}

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值