1. 程式人生 > 其它 >CF1593 E. Gardener and Tree(拓撲排序)

CF1593 E. Gardener and Tree(拓撲排序)

目錄

Description

有一棵樹,每次操作將葉子節點或根節點刪除掉, \(k\) 此操作之後會剩下多少節點

State

\(1<=t<=10^4\)

\(1<=n<=4*10^5\)

\(1<=k<=2*10^5\)

Input

6

14 1
1 2
2 3
2 4
4 5
4 6
2 7
7 8
8 9
8 10
3 11
3 12
1 13
13 14

2 200000
1 2

3 2
1 2
2 3

5 1
5 1
3 2
2 1
5 4

6 2
5 1
2 5
5 6
4 2
3 4

7 1
4 3
5 1
1 3
6 1
1 7
2 1

Output

7
0
0
3
1
2

Solution

思路是拓撲排序很容易知道,無向圖中要避免一個節點放入重複放入佇列(需要嚴格控制進佇列的條件或 \(vis\) 陣列判斷)

$hint: $ 當只有一個節點的時候,答案應該是 \(0\)


Code

const int N = 4e5 + 5;
 
    int n, m, k, _;
    int a[N];
    vector<int> v[N]; 
    int into[N];
    int vis[N];

void init()
{
    for(int i = 1; i <= n; i ++){
        v[i].clear();
        into[i] = 0;
        vis[i] = 0;
    }
}

signed main()
{
    // IOS;
    rush(){
        sdd(n, m);
        int x, y;
        init();
        rep(i, 1, n - 1){
            sdd(x, y);
            v[x].pb(y);
            v[y].pb(x);
            into[x] ++;
            into[y] ++;
        }
        if(n == 1){
            pd(0);
            continue;
        }
        int ans = n;
        queue<int> q;
        for(int i = 1; i <= n; i ++){
            if(into[i] == 1){
                q.push(i);
                vis[i] = 1;
            }
        }
        while(m --> 0 && ans){
            int sz = q.size();
            while(sz --> 0){
                int u = q.front();
                q.pop();
                ans --;
                for(auto it : v[u]){
                    if(vis[it]) continue;
                    into[it] --;
                    if(into[it] == 1){
                        q.push(it);
                        vis[it] = 1;
                    }
                }
            }
        } 
        pd(ans);
    }
    // PAUSE;
    return 0;
}