jzoj3519-灵能矩阵【LCM,树形dp】
生活随笔
收集整理的這篇文章主要介紹了
jzoj3519-灵能矩阵【LCM,树形dp】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目大意
一棵樹,每個葉子節點有權值,每個點的權值是它這棵子樹中的所有葉子節點權值之和。可以減少葉子節點的值,要求減少最少的值使得對于每個點,它的所有子節點的權值都相等。
解題思路
如果將葉子節點的深度優先訪問順序排好,那么就是一個序列。對于這個序列,我們只可以區間減少。那么我們可以先將一個區間減到滿足要求,再考慮更大的區間。
對于每個點我們先不考慮原本權值。我們對于每個點我們構建一種系數xxx。
對于第iii個點,如果它的子樹已經平衡了,那么當我們將總值減去xix_ixi?的倍數時它還是平衡的。
明顯這個系數為limx=LCM(wsonx)lim_x=LCM(w_{son_x})limx?=LCM(wsonx??)
然后這個點的
wx=min{wsonx}?son_numx+min{wsonx}?son_numx%limxw_x=min\{w_{son_x}\}*son\_num_x+min\{w_{son_x}\}*son\_num_x\% lim_xwx?=min{wsonx??}?son_numx?+min{wsonx??}?son_numx?%limx?
codecodecode
#include<cstdio> #include<vector> #include<algorithm> #define ll long long #define lcm(x,y) x*y/__gcd(x,y) using namespace std; const ll N=100010; vector<int> a[N]; ll n,x,y,w[N],ans,size[N],lim[N]; void dp(ll x) {lim[x]=1;if(w[x]) return;ll minw=1e18,sum=0;for(ll i=0;i<a[x].size();i++){ll y=a[x][i];dp(y);lim[x]=lcm(lim[x],lim[y]);minw=min(minw,w[y]);sum+=w[y];}lim[x]*=a[x].size();w[x]=minw*a[x].size()-minw*a[x].size()%lim[x];ans+=sum-w[x]; } int main() {//freopen("pylon.in","r",stdin);//freopen("pylon.out","w",stdout);scanf("%lld",&n);for(ll i=1;i<=n;i++)scanf("%lld",&w[i]);for(ll i=1;i<n;i++){ll x,y;scanf("%lld%lld",&x,&y);a[x].push_back(y);}dp(1);printf("%lld",ans); }總結
以上是生活随笔為你收集整理的jzoj3519-灵能矩阵【LCM,树形dp】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 比亚迪10月销量首破30万辆,今年累计已
- 下一篇: 苹果 Apple Arcade 新增《迪