1. 程式人生 > 其它 >Codeforces Round #748 (Div. 3) E. Gardener and Tree

Codeforces Round #748 (Div. 3) E. Gardener and Tree

簡單的拓撲排序應用。
https://codeforces.com/contest/1593/problem/E

題意

給一顆樹,每次刪除當前樹所有的葉子結點,問刪除 \(k\) 輪後還剩多少點

Tutorial

由於一棵樹的深度最高是 \(O(n)\) 刪除葉子結點的過程又顯然是個拓撲排序裡去掉入度為 \(0\) 節點的操作,因此這題可以直接暴力而我居然想搞直徑

點選檢視程式碼
#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <vector>
typedef long long ll;
#define endl '\n'
#define P pair<int, int>
#define eps 1e-8
#define IOS                  \
    ios::sync_with_stdio(0); \
    cin.tie(0);              \
    cout.tie(0);
using namespace std;

const int N = 4e5 + 5;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
typedef long long ll;
vector<int> mp[N];
int vis[N], deg[N],n,m,k;
int main() {
    IOS
    int T;
    cin>>T;
    while(T--){
        cin >> n>>k;
        for(int i=0,u,v;i<n-1;i++){
            cin>>u>>v;
            mp[u].push_back(v);
            mp[v].push_back(u);
            deg[u]++;
            deg[v]++;
        }

        int cnt = n;
        vector<int> now;
        vector<int> nxt;
        for(int i=1;i<=n;i++){
            if(deg[i] <= 1){
                now.push_back(i);
                vis[i] = 1;
            }
        }
        cnt -= now.size();
        k--;
        while(k-- && now.size()){    
            
            for(auto u:now){
                for(auto v:mp[u]){
                    if(!vis[v]) deg[v]--;
                    
                    if(deg[v] <= 1 && !vis[v]){
                        nxt.push_back(v);
                        vis[v] = 1;
                    }

                }
            }
            cnt -= nxt.size();
            now = nxt;
            nxt.clear();
        }
        cout << max(0,cnt) << endl;

        for (int i = 1; i <= n; i++) mp[i].clear(), deg[i] = 0,vis[i] = 0;
    }
}