1. 程式人生 > 其它 >Tree Infection(1600 二分)

Tree Infection(1600 二分)

傳送門

一、題意:

在一棵樹上進行1s內進行兩種操作:

1、Spreading:對於每個節點,如果有葉子節點被感染了,可以選擇另外一個沒有被感染過的葉子節點進行感染

2、Injection:可以選擇任意一個健康節點進行感染

問將所有節點感染花費的最少時間?

 

二、思路:

二分,優先葉子節點多的塊進行Injection,剩下的能否在mid - 1時間內感染完成

 

三、程式碼:

 1 #include <bits/stdc++.h>
 2 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 }