題目大意:給出一棵
老年選手復健中……
結論1.最壞情況下初始叛徒一定是一個葉節點
證明:顯然如果初始叛徒不能策反它的父親那它就不能策反任何節點了
假設初始叛徒爲
結論2.最終的所有叛徒一定是某個節點爲根的子樹中的所有節點
由上一個結論,顯然
然後我們就可以DP了。
令
min裏面的兩個,一個是
答案等於
時間複雜度
帶log會T。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 500500
using namespace std;
int n,m;
struct abcd{
int to,next;
}table[M];
int head[M],tot;
int size[M];
double f[M],ans;
//f[x]表示如果讓以x爲根的子樹不叛變,答案最小多少
void Add(int x,int y)
{
table[++tot].to=y;
table[tot].next=head[x];
head[x]=tot;
}
void DFS(int x)
{
int i;
size[x]=1;
for(i=head[x];i;i=table[i].next)
{
DFS(table[i].to);
size[x]+=size[table[i].to];
}
}
void Tree_DP(int x)
{
int i;
if(!head[x])
{
f[x]=1;
return ;
}
for(i=head[x];i;i=table[i].next)
{
Tree_DP(table[i].to);
f[x]=max(f[x],min(f[table[i].to],(double)size[table[i].to]/(size[x]-1) ));
}
if(size[x]>m)
ans=max(ans,f[x]);
}
int main()
{
cin>>n>>m;
for(int x,i=2;i<=n;i++)
{
scanf("%d",&x);
Add(x,i);
}
DFS(1);
Tree_DP(1);
printf("%.10lf\n",ans);
return 0;
}