CF2050G Tree Destruction 题解
【题意简述】#
你有一棵树,你可以从里面删除一条链上的节点,问剩下的点的联通块数量最大是多少。
【思路】#
一眼树形 dp,默认根为 \(1\)。
我们以这棵树的 \(1\) 节点作为示例。
设 \(dp_{i,0}\) 表示 \(i\) 节点的子树中选一条链,\(i\) 不在链上的最大联通块数。
设 \(dp_{i,1}\) 表示 \(i\) 节点的子树中选一条链,\(i\) 在链端点的最大联通块数。
设 \(dp_{i,2}\) 表示 \(i\) 节点的子树中选一条链,\(i\) 在链中间的最大联通块数。
-
\(dp_{i,0}\):\(i\) 不在链上,意味着一定是 \(i\) 的某一个子节点的子树内有一条链。
-
\(dp_{i,1}\):\(i\) 在链的端点,意味着
-
\(dp_{i,2}\):\(i\) 在链的中间,意味着
然后就很好写了。
【Code】#
#include <bits/stdc++.h>
using namespace std;
vector<int>Edge[200005];
int n,u,v,dp[200005][3];
void DFS(int u,int fa){
int soncnt=0,max0=0,max1=0,sec1=0,max2=0;
for(auto v:Edge[u]){
if(v!=fa){
DFS(v,u),soncnt++;
max0=max(max0,dp[v][0]);
max2=max(max2,dp[v][2]);
if(dp[v][1]>max1){
sec1=max1;
max1=dp[v][1];
}else if(dp[v][1]>sec1){
sec1=dp[v][1];
}
}
}
dp[u][0]=max(max0,max(max1,max2)+1);
dp[u][1]=max(soncnt,max1+(soncnt-1));
dp[u][2]=max1+sec1+(soncnt-2);
}
void Main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) dp[i][0]=dp[i][1]=dp[i][2]=0,Edge[i].clear();
for(int i=1;i<=n-1;i++){
scanf("%d%d",&u,&v);
Edge[u].push_back(v);
Edge[v].push_back(u);
}
DFS(1,0);
printf("%d\n",max({dp[1][0],dp[1][1],dp[1][2]}));
}
int T;
int main()
{
scanf("%d",&T);
while(T--) Main();
return 0;
}
【后记】#
祝贺我自己,在上蓝前的最后一场 Div.3 AK。
两发罚时全是数组开小,乐。
以后就打不了了。
作者:Sundar-2022
出处:https://www.cnblogs.com/Sundar-2022/p/18591492
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
分类:
Codeforces
, 题解
标签:
Codeforces
, 题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】