题目:

​ 给你一棵树,每次操作你可以删去一条边,最少需要多少次操作使每个节点的度数都\(<=k\)

分析:

​ 我们可以想一想如何贪心,对于本题,最优的结果是让任意一个点连的边最多越好(但不能超过K,所以从树的底部到根,能删就删。这样可以保证,删的边数是最少的。

实现:

​ 用dfs跑,注意的是如果没有父节点,tot[u]的初始化为0,其余都是有一个父节点提供一条边。对于一个节点,能删就删。

#include using namespace std;#define rep(i, a, n) for(int i = a; i < n; i++)#define all(x) x.begin(), x.end()#define pb push_back#define ios ios::sync_with_stdio(false);cin.tie(0);#define debug(x) cout << x << endl;#define SZ(x) (int)x.size()typedef long long LL;typedef unsigned long long ULL;typedef pair PII;const int inf = 0x3f3f3f3f;void read(int &x) {int s = 0, f = 1; char ch = getchar(); while(!isdigit(ch)) {f = (ch == '-' ? -1 : f); ch = getchar();} while(isdigit(ch)) {s = s * 10 + ch - '0'; ch = getchar();} x = s * f;}const int N = 100005;int n, k;vector g[N];int tot[N];int res;void init(int len){rep(i, 1, len + 1)g[i].clear(), tot[i] = 0;res = 0;}void dfs(int u, int fa){tot[u] = fa > 0;for(int v : g[u]){if(v == fa) continue;dfs(v, u);tot[u] ++;}if(tot[u] > k)res += tot[u] - k, tot[fa] --;}void solve(){cin >> n >> k;init(n);rep(i, 1, n){int u, v; cin >> u >> v;g[u].pb(v); g[v].pb(u);}dfs(1, -1);cout << res <> _;while(_--)solve();}