C. Tree Infection
阿新 • • 發佈:2022-04-09
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)
輪,最後如果need
比x
小就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); }