C. Tree Infection

C. Tree Infection

思路:

二分答案。我们可以把所有儿子结点的数目存到一个vector里面,然后按照从大到小排序,肯定贪心的先染儿子数量多的点。如何写check?假如需要x轮完成染色,当前实际需要need轮,那么至少需要need += vector.size() + 1轮,1是染根节点,vector.size()是保证每个结点的儿子节点至少有一个被染色,然后我们贪心先染色儿子数目多的。假如是第i + 1轮开始染色,那么到x轮结束,它一共有1 + x - i - 1个儿子被染色,如果这个值比实际儿子数量多,则需要 need += q[i] - (x - i)轮,最后如果needx小就return true, 反之 return false

bool check(int x){
	int need = m + 1;
	for(int i = 0; i < m; i ++  ){
		need += max(0, (q[i] - 1) - (x - i - 1));
	}
	return need <= x;
}

void solve()
{
	scanf("%d",&n);
	for(int i = 1; i <= n; i ++ ) du[i] = 0;
	q.clear();
	for(int i = 1; i <= n - 1; i ++ ){
		int x;
		scanf("%d",&x);
		du[x] ++;
	}
	for(int i = 1; i <= n; i ++ ){
		if(du[i]) q.pb(du[i]);
	}
	sort(all(q), greater<int>());
	m = sz(q);
	int l = 0, r = n;
	while(l < r){
		int mid = l + r >> 1;
		if(check(mid)) r = mid;
		else l = mid + 1;
	}
	printf("%d\n",l);
}
posted @ 2022-04-09 21:03  合肥学院王星力  阅读(67)  评论(0)    收藏  举报