Codeforces Round #781
C. Tree Infection
time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

A tree is a connected graph without cycles. A rooted tree has a special vertex called the root. The parent of a vertex vv (different from root) is the previous to vv vertex on the shortest path from the root to the vertex vv. Children of the vertex vv are all vertices for which vv is the parent.

You are given a rooted tree with nn vertices. The vertex 11 is the root. Initially, all vertices are healthy.

Each second you do two operations, the spreading operation and, after that, the injection operation:

  1. Spreading: for each vertex vv, if at least one child of vv is infected, you can spread the disease by infecting at most one other child of vv of your choice.
  2. Injection: you can choose any healthy vertex and infect it.

This process repeats each second until the whole tree is infected. You need to find the minimal number of seconds needed to infect the whole tree.

Input

The input consists of multiple test cases. The first line contains a single integer tt (1≤t≤1e4) — the number of test cases. Description of the test cases follows.

The first line of each test case contains a single integer nn (2≤n≤2e5) — the number of the vertices in the given tree.

The second line of each test case contains n−1n−1 integers p2,p3,…,pnp2,p3,…,pn (1≤pi≤n), where pipi is the ancestor of the ii-th vertex in the tree.

It is guaranteed that the given graph is a tree.

It is guaranteed that the sum of nn over all test cases doesn't exceed 2e5.

 1 # include<iostream>
2 # include<algorithm>
3 # include<queue>
4 # define int long long
5 # define endl "\n"
6 using namespace std;
7 const int N = 1000050;
8 int f[N],vis[N];
9
10 void solve(){
11 int n;
12 cin>>n;
13 for(int i = 1;i <= n;++i) f[i] = 0;
14 for(int i = 2;i <= n;++i){
15 int x;
16 cin>>x;
17 f[x]++;
18 }
19 int l = 1,r = n,res = n;
20 while(l <= r){
21 int mid = (l+r)>>1;
22 for(int i = 0;i <= n;++i) vis[i] = 0;
23 priority_queue<pair<int,int> > q;
24
25 for(int i = 1;i <= n;++i) if(f[i]) q.push({f[i],i});
26 q.push({1,0});
27 for(int i = 1;i <= mid;++i){
28 if(q.empty()) break;
29 auto now = q.top();q.pop();
30 if(!vis[now.second]) now.first -=mid - i+1,vis[now.second] = 1;
31 else now.first--;
32 if(now.first > 0) q.push(now);
33 }
34 if(q.empty()) res = mid,r = mid-1;
35 else l = mid+1;
36 }
37 cout<<res<<endl;
38 }
39
40 int tt;
41 signed main(){
42 ios::sync_with_stdio(false);
43 cin.tie(nullptr);
44 cout.tie(nullptr);
45 cin>>tt;
46 while(tt--){
47 solve();
48 }
49
50
51 return 0;
52 }

  二分实在是精彩

根据题意将相同父节的个数进排序,每次对个数最多的进行操作

如果尚未被感染则选择注射,如果已经被注射过,则选择传播给相同父节点的子节点

通过priority_queue来进行排序,每次取对头进行操作,通过vis进行对节点(相同父节点)的判断是否被感染过

而二分的是操作次数(二分答案),有两种可能,如果操作次数内使得队列为空说明在当前操作次数可以满足全部感染,继续查找更小的操作次数

否则就不能满足全部感染,查找更大的操作次数

最新文章

  1. MVC Razor视图引擎的入门
  2. 实现UITextView的placeholder
  3. 初识selendroid
  4. MyJni撒旦
  5. 什么是作用域链,什么是原型链,它们的区别,在js中它们具体指什么?
  6. sass的视频教程
  7. Python 文件I/O
  8. TCP/IP协议原理与应用笔记25:网际协议(IP)之 数据报(Datagram)
  9. 第三方类AFNetworking
  10. BZOJ 2626 JZPFAR(KD-tree)
  11. ContentType 属性 MIME
  12. Fill-rate, Canvases and input 【译】
  13. angularjs jsonp跨域
  14. c#坐标系互相转换
  15. 期货大赛项目|五,表格插件datatatables在MVC中的应用
  16. 2019/4/17 wen 注解、垃圾回收、多线程
  17. cesium3dtiles位置改变
  18. POI--各种样式的XSSFCellStyle的生成
  19. 一、Dev
  20. MySQL Crash Course #10# Chapter 19. Inserting Data

热门文章

  1. python九周周末总结
  2. 【MySQL】DDL因Waiting for table metadata lock卡住
  3. 如何在 Jenkins CI/CD 流水线中保护密钥?
  4. aardio + .NET 快速开发独立 EXE 程序,可防 ILSpy 反编译
  5. Git Rebase-提交整洁之道
  6. dotnet7 aot编译实战
  7. Dockerfile文件:设置变量启动的时候传递进去
  8. mongodb停止关闭服务
  9. 1_JavaWeb引言
  10. 【设计模式】Java设计模式 - 命令模式