NC20666. 梦中的勇士
描述
输入描述
第一行一个数T(1<=T<=2000),表示测试样例的数量。
每一个测试样例中,第一行一个数字n(2<=n<=100000)表示交叉路口的数量。
接下来的n-1行,每行两个数字ai,bi(0<=ai,bi<=10^9),表示第2,3,...,n个路口打败怪兽失去的血量和得到的血量。
再接下来的n-1行,每行两个数字u和v,表示u和v路口之间有道路连接。
保证∑n≤10^6.
输出描述
对于每一个样例,输出一个单独的数字,表示最初的最小的血量。每个数字占一行。
示例1
输入:
1 4 2 6 5 4 6 2 1 2 2 3 3 4
输出:
3
C++(clang++ 11.0.1) 解法, 执行用时: 15ms, 内存消耗: 2744K, 提交时间: 2023-05-30 21:43:38
#include<bits/stdc++.h> #define N 100010 #define INF 1e9 #define LL long long #define pb push_back #define cl clear #define si size #define lb lowwer_bound #define eps 1e-8 #define P 1000000007 #define IO ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); using namespace std; struct node { LL x,y,id; friend bool operator <(const node & a ,const node &b) { if(a.x<a.y&&b.x<b.y) return a.x>b.x; if(a.y<=a.x&&b.y<=b.x) return a.y<b.y; return a.x>=a.y; } }a[N]; priority_queue<node>q; int fa[N]; bool v[N]; vector<int>G[N]; void dfs(int x,int p){ for(auto i:G[x]) if(i!=p) fa[i]=x,dfs(i,x); } int getfa(int x){ if(v[fa[x]]==1) return getfa(fa[x]); return fa[x]; } int main() { IO int T; cin>>T; while(T--) { int n;cin>>n; for(int i=2;i<=n;i++){ int x,y;cin>>x>>y; a[i]={x,y,i}; G[i].clear(); v[i]=0; q.push(a[i]); } G[1].clear();v[1]=0;fa[1]=1; a[1].x=a[1].y=a[1].id=0; for(int i=2;i<=n;i++){ int u,v;cin>>u>>v; G[u].push_back(v); G[v].push_back(u); } dfs(1,0); while(!q.empty()) { node c=q.top(); q.pop(); if(v[c.id]) continue; int ff=getfa(c.id); a[ff].x+=max(a[ff].y,a[c.id].x)-a[ff].y; if(a[ff].y>a[c.id].x) a[ff].y-=(a[c.id].x-a[c.id].y); else a[ff].y=a[c.id].y; if(ff!=1) q.push(a[ff]); v[c.id]=1; } cout<<a[1].x<<endl; } return 0; }