樹-P1351 聯合權值
阿新 • • 發佈:2018-12-02
題目連結:
https://www.luogu.org/problemnew/show/P1351
看題解,還是一知半解,先紀錄一下,後續再搞。
/* 先看求聯合權值的和。稍稍對題意進行變形,即為:對每一個點,找到與它相連的所有點,那些點之間兩兩權值相乘,最後把所有乘積相加(並取餘,別忘了qwq)。 我們想象:每連上一條邊,便進行一次“操作”。定義一個數組S,用S[i]記錄第i個點周圍已經連上的點的權值之和。連上一條邊時,比方說從a點到b點,對這兩個點分別進行操作,拿a點舉例: 首先將b點的權值乘以已經連上a點的所有點的權值之和(就是S[a]),加到總結果sum上;然後把b點的權值加到S[a]上。 b點的操作同理。這樣的話,從第一條邊連到最後一條邊,sum累積了一半的聯合權值總和,x2便是正確答案。 (稍稍想想大概就是這麼回事吧...) 再看求最大值。類似地,定義一個數組M,用M[i]記錄第i個點周圍已經連上的點的權值的最大值。類似於上面的操作,每連上一條邊,分別更新相應的M[a]、M[b],以及全域性聯合權值的最大值ans。 最後...別忘開long long否則70分orz */ #include<iostream> #define N 200010 #define mod 10007 using namespace std; long long w[N],A[N],B[N],S[N],M[N],sum,ans; int n; int main() { cin>>n; for(int i=1;i<n;i++) cin>>A[i]>>B[i]; for(int i=1;i<=n;i++) cin>>w[i]; for(int i=1;i<n;i++) { int ta=A[i],tb=B[i]; ans=max(ans,M[ta]*w[tb]); M[ta]=max(M[ta],w[tb]);//M[i]記錄第i個點周圍已經連上的點的權值的最大值 sum=(sum+S[ta]*w[tb])%mod; S[ta]+=w[tb];//S[i]記錄第i個點周圍已經連上的點的權值之和 ans=max(ans,M[tb]*w[ta]); M[tb]=max(M[tb],w[ta]); sum=(sum+S[tb]*w[ta])%mod; S[tb]+=w[ta]; } cout<<ans<<" "<<(sum*2)%mod; return 0; }