Tree Infection(1600 二分)
传送门
一、题意:
在一棵树上进行1s内进行两种操作:
1、Spreading:对于每个节点,如果有叶子节点被感染了,可以选择另外一个没有被感染过的叶子节点进行感染
2、Injection:可以选择任意一个健康节点进行感染
问将所有节点感染花费的最少时间?
二、思路:
二分,优先叶子节点多的块进行Injection,剩下的能否在mid - 1时间内感染完成
三、代码:
1 #include2 using namespace std; 3 4 const int N = 2e5 + 10; 5 int n, x, cnt, a[N]; 6 vector<int> g[N]; 7 8 bool check(int x){ 9 int rest = 0; 10 for(int i = 1, j = x - 1; i <= cnt; i++, j--){ 11 rest += max(0, a[i] - j); 12 } 13 return x - cnt >= rest; 14 } 15 16 void accept() { 17 cin >> n; 18 for(int i = 1; i <= n; ++i) g[i].clear(); 19 for(int i = 2; i <= n; ++i) { 20 cin >> x; 21 g[x].push_back(x); 22 } 23 24 cnt = 1, a[1] = 0; 25 for(int i = 1; i <= n; ++i) { 26 if(g[i].size()) a[++cnt] = g[i].size() - 1; 27 } 28 sort(a + 1, a + 1 + cnt, greater<int>()); 29 30 int l = cnt, r = n; 31 while(l < r) { 32 int mid = l + r >> 1; 33 if(check(mid)) r = mid; 34 else l = mid + 1; 35 } 36 37 cout << l << "\n"; 38 } 39 40 signed main() { 41 ios::sync_with_stdio(false); 42 cin.tie(nullptr); 43 int t; 44 cin >> t; 45 for(int i = 0; i < t; ++i) accept(); 46 return 0; 47 }