1. 程式人生 > 其它 >C. Tree Infection

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);
}