CF1946C 题解

思路

求最小的最大,显然是二分题。然后判断函数只需要从根节点递归,如果当前节点数 mid\ge mid 了,那就删掉它与父亲节点的边,并累加一下计数器。如果删边数量已经够多了,那么只要看剩下的整棵树的节点数是否也 mid\ge mid 就行啦。

代码

# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair <int, int> pii;
int t, n, l, r, mid, best, k, x, y, tot;
vector <int> v[100005];
int dfs (int x, int f) {
	int s = 1;
	for (int& i : v[x])
		if (i != f)
			s += dfs (i, x);
	if (tot < k && s >= mid) {
		++ tot;
		return 0;
	}
	return s;
}
bool check () {
	tot = 0;
	return dfs (1, 0) >= mid && tot >= k;
}
int main () {
	ios::sync_with_stdio (0);
	cin.tie (0);
	cout.tie (0);
	cin >> t;
	while (t --) {
		cin >> n >> k;
		for (int i = 1; i <= n; ++ i)
			v[i].clear ();
		for (int i = 1; i < n; ++ i)
			cin >> x >> y, v[x].emplace_back (y), v[y].emplace_back (x);
		l = 1, r = n;
		while (l <= r) {
			mid = l + r >> 1;
			if (check ())
				l = mid + 1, best = mid;
			else
				r = mid - 1;
		}
		cout << best << '\n';
	}
	return 0;
}
posted @ 2024-04-03 12:56  Vitamin_B  阅读(11)  评论(0)    收藏  举报  来源