CCA subtree (tree dp)

https://ac.nowcoder.com/acm/contest/11168/C


Ideas:

Calculate the subtree rooted at each point and then brute force n^2 update can be done.

But to improve dp to on.

definition:

mx[u]: The maximum value of the subtree with u as the total root .

So  each point can find a comprehensive maximum value in the big subtree of u itself or the subtree of a son or grandson in u.

Then when running dfs at this time, a point represents the optimal subtree state below one side. Then enumerate in this way to reach the enumeration of all states.

Different from changing roots, running post-order, update the leftmost large subtree after updating the leftmost large subtree, then update the inside of the middle large subtree, and then update the middle large subtree and the left large subtree. Combine

(The tree dp is still very easy to want to string...

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=2e5+1000;
typedef long long LL;
inline LL read(){LL x=0,f=1;char ch=getchar();	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
LL sum[maxn],mx[maxn],val[maxn];
vector<LL>g[maxn];
LL ans=-1e18;
void predfs(LL u,LL fa){
    sum[u]=val[u];
    for(LL i=0;i<g[u].size();i++){
        LL v=g[u][i];
        if(v==fa) continue;
        predfs(v,u);
        sum[u]+=sum[v];
        ///mx[u]=max(mx[u],sum[v]);///wa的原因:是从子树的每个max状态转移过来写成了sum[]
    }
    mx[u]=max(mx[u],sum[u]);
    for(LL i=0;i<g[u].size();i++){
        LL v=g[u][i];
        if(v==fa) continue;
        mx[u]=max(mx[u],mx[v]);
    }
}
void dfs(LL u,LL fa){
    LL mx1=-1e18;
    LL mx2=-1e18;
    for(LL i=0;i<g[u].size();i++){
        LL v=g[u][i];
        if(v==fa) continue;
        if(mx1<mx[v]){
            mx2=mx1;
            mx1=mx[v];
        }
        else if(mx2<mx[v]){
            mx2=mx[v];
        }///得更完最大值再更新
        dfs(v,u);
    }
    if(mx2!=-1e18) ans=max(ans,mx1+mx2);///后序遍历取dp状态的更新,不同于换根
}
int main(void)
{
  cin.tie(0);std::ios::sync_with_stdio(false);
  LL n;cin>>n;
  for(LL i=1;i<=n;i++) cin>>val[i],mx[i]=-1e17;
  for(LL i=1;i<n;i++){
    LL u,v;cin>>u>>v;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  predfs(1,1);
  dfs(1,1);
  if(ans!=-1e18)  cout<<ans<<"\n";
  else cout<<"Error"<<"\n";
return 0;
}

 

Guess you like

Origin blog.csdn.net/zstuyyyyccccbbbb/article/details/114716041