CF1593E-Gardener-and-Tree-题解

原题面

题意:

给出一个 n 个点的树,删除 k 次叶子节点,求剩下的节点数。

思路:

cntik 最小为多少时点 i 会被删除。

i 将要被删除时,它一定是现在的叶子,联想到拓扑排序的特点,直接跑一遍拓扑排序即可。

初始时所有叶子的 cnt 都为 1,跑完拓扑排序后遍历一遍 cnt 数组统计 cnti>k 的数量,时间复杂度 O(n)

code:

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int N=4e5+10;
int t,n,k,cnt[N],d[N],ans;
bool f[N];
vector<int> g[N];
queue<int> q;
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&k);
ans=0;
memset(f,0,sizeof(f));
memset(d,0,sizeof(d));
memset(cnt,0,sizeof(cnt));
for(int i=1;i<=n;i++)g[i].clear();
for(int i=1,x,y;i<n;i++)
{
scanf("%d%d",&x,&y);
g[x].push_back(y);
g[y].push_back(x);
d[x]++,d[y]++;
}
if(k==0)
{
printf("%d\n",n);
continue;
}
for(int i=1;i<=n;i++)if(d[i]==1)q.push(i),f[i]=cnt[i]=1;
while(!q.empty())
{
int t=q.front();
q.pop();
for(int i=0;i<g[t].size();i++)
{
int v=g[t][i];
if(f[v])continue;
d[v]--;
if(d[v]==1)
{
f[v]=1;
cnt[v]=cnt[t]+1;
q.push(v);
}
}
}
for(int i=1;i<=n;i++)if(cnt[i]>k)ans++;
printf("%d\n",ans);
}
}
posted @   jr_inf  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示