原題連結
題解
樹形dp的想法,遞迴返回的是子樹的最大聯合權值以及聯合權值之和。
首先,根據題目意思可以知曉該無向圖構成的是一棵樹。
由樹形dp的遍歷可知,當我們來到 root結點時,其所有孩子結點的子樹 最大聯合權值 和 聯合權值之和 都已經知曉,我們只需要對其取 max 和 累加 即可。
but,上面是以root結點為中轉結點的情況,所以我們還要考慮root結點與 其父節點的父節點 相連形成的聯合權值的情況,進行特判即可。
code
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=2e5+5; const ll mod=10007; ll head[N],Next[N<<1],to[N<<1],w[N],cnt=1; struct node{ ll MAX_val,sum; node(ll MAX_val,ll sum): MAX_val(MAX_val),sum(sum){} }; void build(int from,int to_){ Next[cnt]=head[from]; to[cnt]=to_; head[from]=cnt++; } node dfs(int root,int f,int g){ int more=w[root]*w[g]*2; node ans(more/2,0); ans.sum=(ans.sum+more)%mod; node x(0,0); ll max1=0,max2=0,val=0,power=0; for (int i=head[root];i>0;i=Next[i]){ if (to[i]==f) continue; val+=w[to[i]]; power+=w[to[i]]*w[to[i]]; x=dfs(int(to[i]),root,f); ans.sum=(ans.sum+x.sum)%mod; ans.MAX_val=max(ans.MAX_val,x.MAX_val); if (w[to[i]]>max1) max1=w[to[i]]; else if (w[to[i]]>max2) max2=w[to[i]]; } if (max1*max2>ans.MAX_val) ans.MAX_val=max1*max2; ans.sum=(ans.sum+val*val-power)%mod; return ans; } int main(){ int n; cin>>n; for (int i=1,u,v;i<n;i++){ cin>>u>>v; build(u,v); build(v,u); } for (int i=1;i<=n;i++) cin>>w[i]; node x=dfs(1,0,0); cout<<x.MAX_val<<" "<<x.sum<<endl; return 0; }