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); } }
分类:
E 动态规划
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源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 逆序对