题意 :
- 给一无根树,每次操作将所有叶子结点去除,问k次操作后还剩多少结点
思路 :
- 输入时存每个点的入度和出度,然后把度 小于等于 1的放入队列并记录为第一层,然后从队头开始弹出元素,枚举当前点的邻边,假设枚举到的邻边的点的度-1后等于1,那么说明它是下一层的点,更新层数并加入队列,最后枚举每个点的层数是否大于k,大于k则是被剩下的点
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#define debug(a) cout << #a << " = " << a << endl;
#define x first
#define y second
using namespace std;
typedef long long ll;
const int N = 4e5 + 10;
int n, m;
int d[N], vis[N];
int h[N], ne[N * 2], e[N * 2], idx; // 无向图
void init()
{
idx = 0;
for (int i = 1; i <= n; i ++ )
h[i] = -1, d[i] = 0, vis[i] = 0;
}
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int _;
cin >> _;
while (_ -- )
{
cin >> n >> m;
init(); // 初始化图
for (int i = 1; i <= n - 1; i ++ )
{
int a, b;
cin >> a >> b;
add(a, b), add(b, a);
d[a] ++ , d[b] ++ ;
}
queue<int> q;
for (int i = 1; i <= n; i ++ )
if (d[i] <= 1)
{
vis[i] = 1;
q.push(i);
}
while (q.size())
{
int t = q.front(); q.pop();
for (int i = h[t]; ~i; i = ne[i])
{
int j = e[i];
if ( -- d[j] == 1)
{
vis[j] = vis[t] + 1;
q.push(j);
}
}
}
int ans = 0;
for (int i = 1; i <= n; i ++ )
if (vis[i] > m)
ans ++ ;
cout << ans << endl;
}
return 0;
}