传送门
一开始以为跟二叉树有关 一看到就头疼 看了题解发现跟二叉树没啥关系,看了好长时间才明白
一秒内可以做俩操作:
- 感染一个健康的节点
- 传染相邻的兄弟节点
思路
sum[i]表示以i为节点的节点个数有几个,一开始去感染最多的那个群体 为什么呢?因为这样可以给这个群体更多的彼此间互相传染的时间,在他互相传染的时间里,我们去感染其他群体如果所有的群体我们都已经感染了一个,计算在这个时间内 每个群体剩余的没有被感染的节点的个数,我们再重复以上操作(找到最多的 去感染,让其传染,在这个时间内去感染其他节点)
就是这样! 直到所有的节点都不健康结束
code
#include<bits/stdc++.h>
using namespace std;
const int N=1e5;
int a[2*N+10];
bool cmp(int x,int y)
{
return x>y;
}
int main()
{
int i,j,k,m,n,sum=0,t;
cin>>t;
while(t--)
{
cin>>n;
a[n+1]=1;根节点
for(i=2;i<=n;i++)
{
int x;
cin>>x;
a[x]++;
}
sort(a+1,a+2+n,cmp);
for(m=1;;m++)
{
if(a[m]==0)
{
m--; //计算有几个群体
break;
}
}
// printf("+++ %d\n",m);
for(i=1;i<=m;i++)
{
a[i]=a[i]-1-(m-i);//计算在感染一轮的时间内 每个群体剩余的未被传染的节点个数
}
sort(a+1,a+1+m,cmp);//从大到小排序
int mx=a[1]>0?1:0;//如果最大的那个群体都已经被感染完 就说明所有的群体在第一轮已经传染完毕
sum=m;第一轮所需m个时间
while(1)
{
if(a[mx]==0)
break;
sum++;
a[mx]--;
mx=0;
for(i=1;i<=m;i++)//每个群体剩下的健康的节点数都要减1
{
if(a[i]<=0)
break;
a[i]--;
if(a[i]>=a[mx])找到最大的剩下的那个群体
mx=i;
}
}
memset(a,0,sizeof(a));
printf("%d\n",sum);
}
return 0;
}