Gardener and Tree 图论,树,队列

在这里插入图片描述
在这里插入图片描述
题意 :

  • 给一无根树,每次操作将所有叶子结点去除,问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;
}

Guess you like

Origin blog.csdn.net/m0_51448653/article/details/121255759