1. 程式人生 > >HDU 6326 Problem H. Monster Hunter (貪心+並查集)*

HDU 6326 Problem H. Monster Hunter (貪心+並查集)*

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

 

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