E93 树形DP+树的直径 P10794『SpOI - R1』架子鼓可以站 C

视频链接:E93 树形DP+树的直径 P10794『SpOI - R1』架子鼓可以站 C_哔哩哔哩_bilibili

 

 

 

 

 

 

P10794 『SpOI - R1』架子鼓可以站 C - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

复制代码
// 树形DP O(n)
#include<bits/stdc++.h>
using namespace std;

int read(){
  int x=0,f=1;char c=getchar();
  while(c>'9'||c<'0'){if(c=='-') f=-1;c=getchar();}
  while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
  return x*f;
}
const int N=200005;
int n,T,ans;
vector<int> e[N];
int d[N],f[N],g[N],h[N];
int D[N][3],S[N][3];

void upd(int u,int v,int dv){
  if(dv>=D[u][0]){
    D[u][2]=D[u][1];S[u][2]=S[u][1];
    D[u][1]=D[u][0];S[u][1]=S[u][0];
    D[u][0]=dv;S[u][0]=v;
  }
  else if(dv>=D[u][1]){
    D[u][2]=D[u][1];S[u][2]=S[u][1];
    D[u][1]=dv;S[u][1]=v;
  } 
  else if(dv>D[u][2])D[u][2]=dv,S[u][2]=v;
}
void dfs(int u){
  int f1=0,f2=0;
  for(int v:e[u]){
    dfs(v);
    d[u]=max(d[u],d[v]+1); 
    upd(u,v,d[v]);
    f[u]=max(f[u],f[v]);  
    g[u]=max(g[u],g[v]+1);
    h[u]=max(h[u],h[v]);  
    if(f[v]>f1) f2=f1,f1=f[v];
    else if(f[v]>f2) f2=f[v];
  }
  f[u]=max(f[u],D[u][0]+D[u][1]+2);
  h[u]=max(h[u],f1+f2);
  
  for(int v:e[u]){
    g[u]=max(g[u],f[v]+(S[u][0]==v?D[u][1]:D[u][0])+1);
    int res=0,cnt=0;
    if(S[u][0]!=v) res+=D[u][0],cnt++;
    if(S[u][1]!=v) res+=D[u][1],cnt++;
    if(cnt<2&&S[u][2]!=v) res+=D[u][2];
    h[u]=max(h[u],f[v]+res+2);
    h[u]=max(h[u],g[v]+(S[u][0]==v?D[u][1]:D[u][0])+2);
  }
}
int main(){
  T=read();
  while(T--){
    n=read();
    for(int i=1;i<=n;i++){
      e[i].clear();
      for(int j=0;j<=2;j++)D[i][j]=-1,S[i][j]=0;
      d[i]=f[i]=h[i]=0; g[i]=-1;
    }
    for(int i=2,x;i<=n;i++)
      x=read(),e[x].push_back(i);
    dfs(1);
    int mx1=-1,mx2=-1; ans=0;
    for(int i:e[1]){
      if(f[i]>mx1) mx2=mx1,mx1=f[i];
      else if(f[i]>mx2) mx2=f[i];
      ans=max(ans,h[i]+2);
    }
    ans=max(ans,mx1+mx2+2);
    if(n==2) ans=1;
    printf("%d\n",ans);      
  }
}
复制代码

 

复制代码
// 换根DP O(n)
#include<bits/stdc++.h>
using namespace std;

int read(){
  int x=0,f=1;char s=getchar();
  while(s>'9'||s<'0'){if(s=='-') f=-1;s=getchar();}
  while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
  return x*f;
}
const int N=200005;
int n,T,ans;
vector<int> e[N];
int d[N],f[N],g[N];
int D[N][3],S[N][3];
vector<int> pre[N],suf[N];

void upd(int u,int v,int c){
  if(c>=D[u][0]){
    D[u][2]=D[u][1];S[u][2]=S[u][1];
    D[u][1]=D[u][0];S[u][1]=S[u][0];
    D[u][0]=c;S[u][0]=v;
  }
  else if(c>=D[u][1]){
    D[u][2]=D[u][1];S[u][2]=S[u][1];
    D[u][1]=c;S[u][1]=v;
  } 
  else if(c>D[u][2])D[u][2]=c,S[u][2]=v;
}
void dfs(int u){
  d[u]=f[u]=0,g[u]=-1;
  int sz=e[u].size();
  pre[u].resize(sz);  
  suf[u].resize(sz);
  for(int i=0;i<e[u].size();i++){
    int v=e[u][i];
    dfs(v);
    pre[u][i]=suf[u][i]=f[v];
    upd(u,v,d[v]+1);
    f[u]=max(f[u],d[u]+d[v]+1); //u子树内的答案
    d[u]=max(d[u],d[v]+1);      //u子树内的最长链
    f[u]=max(f[u],f[v]);
  }
  for(int i=1;i<e[u].size();i++) 
    pre[u][i]=max(pre[u][i-1],pre[u][i]);
  for(int i=e[u].size()-2;i>=0;i--) 
    suf[u][i]=max(suf[u][i+1],suf[u][i]);
}
int MX(int u,int v,int t){
  int cnt=0,s=0;
  for(int i=0;i<3;i++){
    if(S[u][i]==v) continue;
    s+=D[u][i],cnt++;
    if(cnt>=t) break;
  }
  return s;
} 
void dfs2(int u,int d){
  upd(u,0,d);
  for(int i=0;i<e[u].size();i++){
    int v=e[u][i];
    g[v]=g[u];
    if(i) g[v]=max(g[v],pre[u][i-1]);
    if(i+1<e[u].size()) g[v]=max(g[v],suf[u][i+1]);
    g[v]=max(g[v],MX(u,v,2));
    dfs2(v,MX(u,v,1)+1);
  }
  ans=max(ans,f[u]+g[u]+2);
}
signed main(){
  T=read();
  while(T--){
    n=read();
    for(int i=1;i<=n;i++){
      e[i].clear();
      memset(D[i],0,sizeof D[i]);
      memset(S[i],0,sizeof S[i]);
    }
    for(int i=2,x;i<=n;i++){
      x=read();
      e[x].push_back(i);
    }
    int maxv=-1; ans=0;
    for(int i:e[1]){
      dfs(i);
      ans=max(ans,maxv+f[i]+2);
      maxv=max(maxv,f[i]);
      g[i]=-1;
      dfs2(i,0);
    }
    ans=max(ans,maxv+1);
    printf("%d\n",ans);
  }
}
复制代码

 

posted @   董晓  阅读(72)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2023-12-31 C85 树状数组+逆序对 P1966 [NOIP2013 提高组] 火柴排队
2023-12-31 C84 树状数组套权值线段树 P3157 [CQOI2011] 动态逆序对
2023-12-31 C83 树状数组 P1908 逆序对
点击右上角即可分享
微信分享提示