gk的树(贪心 dfs) 哈理工程序设计竞赛
题目:
给你一棵树,每次操作你可以删去一条边,最少需要多少次操作使每个节点的度数都\(<=k\)
分析:
我们可以想一想如何贪心,对于本题,最优的结果是让任意一个点连的边最多越好(但不能超过K,所以从树的底部到根,能删就删。这样可以保证,删的边数是最少的。
实现:
用dfs跑,注意的是如果没有父节点,tot[u]的初始化为0,其余都是有一个父节点提供一条边。对于一个节点,能删就删。
#include <bits/stdc++.h>
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<int, int> 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<int> 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 << '\n';
}
signed main()
{
int _ = 1;
cin >> _;
while(_--)
solve();
}