Problem - 1665C - Codeforces
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:
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≤1041≤t≤104) — 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≤2⋅1052≤n≤2⋅105) — 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≤n1≤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 2⋅1052⋅105.
Output
For each test case you should output a single integer — the minimal number of seconds needed to infect the whole tree.
Example
input
Copy
5 7 1 1 1 2 2 4 5 5 5 1 4 2 1 3 3 1 6 1 1 1 1 1
output
Copy
4 4 2 3 4
Note
The image depicts the tree from the first test case during each second.
A vertex is black if it is not infected. A vertex is blue if it is infected by injection during the previous second. A vertex is green if it is infected by spreading during the previous second. A vertex is red if it is infected earlier than the previous second.
Note that you are able to choose which vertices are infected by spreading and by injections.
本题跟数据结构没有任何关系和树也没有任何关系,可以得知的是,每个有儿子点的所有儿子构成一个集合,1号节点单独构成一个集合(父亲是0),每个集合都必须先有一个主动传入,总共消耗时间是集合数,我们应该先进行主动传入,且按照从大到小的顺序进行主动传入会效果最佳。
由于先大后小不好进行计算,我们排序后,从小到大进行计算
这样我们便对每一个集合进行了最优的主动传入,接下来,把它们全部加入优先队列,对当前最大的进行主动传入,从而使得我们的数据更加平均,消耗时间最短。设置top表示当前主动传入的次数,一旦当前最大值小于等于这个值,我们的被动传入就会将其余的全部传染
#include
#include
#include
#include
#include
#include
#include
# include
# include
using namespace std;
typedef long long int ll;
priority_queueq;
ll sizeson[200000+10];
bool cmp(int x,int y)
{
return x>y;
}
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
memset(sizeson,0,sizeof(sizeson));
for(int i=1;i>x;
sizeson[x]++;
}
sizeson[0]=1;
for(int i=0;i<=n;i++)
{
if(!sizeson[i])
sizeson[i]=0x7f7f7f7f7f7f;
}
sort(sizeson,sizeson+n+1);
int cnt=1;
int ans=0;
for(int i=0;i<=n;i++)
{
if(sizeson[i]==0x7f7f7f7f7f7f)
break;
q.push(max((ll)0,sizeson[i]-cnt));
cnt++;
ans++;
}
ll top=0;
while(q.top()>top)
{
ll now=q.top();
q.pop();
q.push(now-1);
top++;
ans++;
}
while(!q.empty())
q.pop();
cout<