CF1092F Tree with Maximum Cost(dfs+dp)
阿新 • • 發佈:2018-12-23
果然我已經菜到被\(div3\)的題虐哭了
qwq
首先看到這個題,一個比較顯然的想法就是先從1號點開始\(dfs\)一遍,然後通過一些奇怪的方式,再\(dfs\)一遍得到其他點的貢獻。
那麼具體應該這麼做呢。
首先,我們維護兩個陣列\(dis[i]\)表示\(i\)到1的距離,\(sum[i]\)表示\(i\)的子樹中的\(val\)的和。
然後我們考慮,如果從\(fa[x]\)移動到\(x\),相當於\(x\)的子樹內的\(dis\)都要減一,對\(ans\)的貢獻是\(-sum[x]\),然後\(x\)的子樹外面的所有的點的\(dis\)要加一,對\(ans\)的貢獻是\(sum[1]-sum[x]\)
那麼我們只需要兩遍\(dfs\),第二遍\(dfs\),一邊\(dfs\)一邊更新\(ans\)就好。
#include<bits/stdc++.h> #define mk make_pair #define pb push_back #define ll long long #define int long long using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();} while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return x*f; } const int maxn = 4e5+1e2; const int maxm = 2*maxn; int point[maxn],nxt[maxm],to[maxm]; int dis[maxn],sum[maxn]; int ans; int n,m,cnt; int tmp; int val[maxn]; void addedge(int x,int y) { nxt[++cnt]=point[x]; to[cnt]=y; point[x]=cnt; } void dfs(int x,int fa,int dep) { sum[x]=val[x]; dis[x]=dep; for (int i=point[x];i;i=nxt[i]) { int p = to[i]; if(p==fa) continue; dfs(p,x,dep+1); sum[x]+=sum[p]; } } void solve(int x,int fa,int now) { ans=max(ans,now); for (int i=point[x];i;i=nxt[i]) { int p=to[i]; if (p==fa) continue; solve(p,x,now+sum[1]-sum[p]-sum[p]); } } signed main() { n=read(); for (int i=1;i<=n;i++) val[i]=read(); for (int i=1;i<n;i++) { int x=read(),y=read(); addedge(x,y); addedge(y,x); } dfs(1,0,0); for (int i=1;i<=n;i++) tmp=tmp+dis[i]*val[i]; ans=tmp; //cout<<ans<<endl; solve(1,0,tmp); cout<<ans; return 0; }