2020牛客暑期多校第九場 B Groundhog and Apple Tree
阿新 • • 發佈:2020-08-13
B Groundhog and Apple Tree
題意:
有一棵樹,經過每條邊會消耗一定體力,到達一個節點的時候可以恢復一定的體力,停下來休息時每一秒也可以恢復一點體力,
求至少需要恢復多少秒使得可以從節點1開始遍歷到每個節點再回到節點1。
體力不能為負數,可以從0-正無窮,經過重複的節點時候不能再恢復體力,樹上每條邊最多隻能遍歷兩次
做法:初步考慮下我們想要恢復的時間較少,且需要遍歷每個子樹,對於根節點來說,
訪問一顆子樹需要的總體力是一個定值,所以我們只需要考慮訪問的順序帶來的影響。也就是遍歷整棵樹可以分成若干棵子樹的遍歷——考慮樹形dp
定義狀態:
Sta[i]表示i節點為根的子樹的答案(需要的最少體力值)
Data[i]表示遍歷i的子樹後體力的變化,可能為負
則轉移式:
然後就是Sta的轉移:
假設所有的data和子樹的sta求好了,對於當前節點則只需要考慮遍歷子樹的順序:
1.data>=0,對於這種,我們應該先走sta較小的,這樣可以保留最大的體力值,減少休息的時間
2.data<0,需要走sta+data較大的,這樣可以保證休息時間更少
然後跑樹形dp即可
點選檢視程式碼塊
#include <bits/stdc++.h> #define ed end() #define bg begin() #define mkp make_pair #define pb push_back #define v(T) vector<T> #define all(x) x.bg,x.ed #define newline puts("") #define si(x) ((int)x.size()) #define rep(i,n) for(int i=1;i<=n;++i) #define rrep(i,n) for(int i=0;i<n;++i) #define srep(i,s,t) for(int i=s;i<=t;++i) using namespace std; typedef long long ll; typedef pair<int,int> pii; const int maxn = 1e5+10; const int inf = 0x7f7f7f7f; const ll inf_ll = 1ll*inf*inf; const int Mod = 1e9+7; const double eps = 1e-7; struct node{ int to;ll v; node(){} node(int _to,ll _v){ to=_to;v=_v; } bool friend operator<(node a,node b){ return a.v<b.v; } }; ll val[maxn],sta[maxn],data[maxn]; vector<node> vec[maxn]; void dfs(int x,int fa) { data[x]=val[x];sta[x]=0; vector<pair<ll,node> > vp1,vp2;//vp1 part1,vp2 part2 for(int i=0;i<vec[x].size();i++){ node s=vec[x][i]; if(s.to==fa) continue; dfs(s.to,x); data[s.to]-=s.v*2; //由於當前這條邊要走兩遍,所以可以直接壓到子兒子裡時要*2 sta[s.to]+=s.v; //這裡由於只要考慮能不能走到子兒子就可以了,req是需要準備的Hp,所以不用*2 data[x]+=data[s.to]; if(data[s.to]>=0) vp1.push_back(make_pair(sta[s.to],s)); else vp2.push_back(make_pair(sta[s.to]+data[s.to],s)); } sort(vp1.begin(),vp1.end()); sort(vp2.begin(),vp2.end()); reverse(vp2.begin(),vp2.end());//倒序 ll now=val[x]; for(int i=0;i<vp1.size();i++){ node son=vp1[i].second; if(now<sta[son.to]) sta[x]+=sta[son.to]-now,now=sta[son.to]; now+=data[son.to];//減去需要的Hp,然後加上遍歷後能得到的Hp if(now<0) sta[x]+=-now,now=0;//如果走著走著變成負了,要調成正的 }for(int i=0;i<vp2.size();i++){ node son=vp2[i].second; if(now<sta[son.to]) sta[x]+=sta[son.to]-now,now=sta[son.to]; now+=data[son.to]; if(now<0) sta[x]+=-now,now=0;//同上 } } int main() { int t,n,x,y;ll z; scanf("%d",&t); while(t--){ scanf("%d",&n); for(int i=0;i<=n;i++) vec[i].clear();//記得清零!!! for(int i=1;i<=n;i++) scanf("%lld",&val[i]); for(int i=1;i<n;i++){ scanf("%d%d%lld",&x,&y,&z); vec[x].push_back(node(y,z)); vec[y].push_back(node(x,z)); } dfs(1,-1); printf("%lld\n",sta[1]); } }