[USACO10MAR]偉大的奶牛聚集Great Cow Gat…
阿新 • • 發佈:2018-11-01
題目
https://www.luogu.org/problemnew/show/P2986
思路
我們可以做如下假設:
① 所有的牛首先到達了1號節點
② 3號節點以及他子樹上的節點都需要退回1->3的路徑的長度
③ 除了3號節點以及他子樹上的節點都需要前進1->3的路徑的長度
通過上面的三條東西,我們就可以從任意一個父節點推出子節點的時間
所以,又是一遍O(n)的計算就可以推出最終的答案
程式碼
#include<cstdio> #include<cstdlib> #include<iostream> #include<cstring> #include<cmath> #include<algorithm> #define ll long long const int maxn=1e5+5; const int maxm=3e5+5; using namespace std; ll n,c[maxn],first[maxn],nxt[maxm],a[maxm],b[maxm],l[maxm],vis[maxn]; ll ju[maxn],dp[maxn],son[maxn],sum; void dfs1(int x){ vis[x]=1; ll k=first[x]; while(k!=-1){ if(!vis[b[k]]){ ju[b[k]]=ju[x]+l[k] ; dfs1(b[k]); son[x]+=son[b[k]]; } k=nxt[k]; } return ; } void dfs2(int x){ vis[x]=1; ll k=first[x]; while(k!=-1){ if(!vis[b[k]]){ dp[b[k]]=dp[x]-son[b[k]]*l[k]+(sum-son[b[k]])*l[k]; dfs2(b[k]); } k=nxt[k]; } return; } int main(){ cin>>n; for(ll i=1;i<=2*n;i++) first[i]=-1; for(ll i=1;i<=n;i++){ cin>>c[i]; son[i]+=c[i]; sum+=c[i]; } for(ll i=1;i<=2*(n-1);i++){ cin>>a[i]>>b[i]>>l[i]; nxt[i]=first[a[i]]; first[a[i]]=i; i++; a[i]=b[i-1];b[i]=a[i-1];l[i]=l[i-1]; nxt[i]=first[a[i]]; first[a[i]]=i; } dfs1(1); for(ll i=2;i<=n;i++) { dp[1]+=ju[i]*c[i]; vis[i]=0; } dfs2(1); ll ans=1000000000000005ull; for(ll i=1;i<=n;i++) ans=min(ans,dp[i]); cout<<ans; return 0; }