您的位置:首页 > 其它

BZOJ4726 [POI2017]Sabota?

2016-11-28 03:09 309 查看
打完一场cf,等分顺便日一道POI2017

首先显然最劣情况初始的叛徒肯定是叶子

并且带头叛变的人一定是从某个叶子往上走一条链

因为如果i没有带头叛变,那么i的父亲也一定不会带头叛变,证明显然

f[i]表示i不带头叛变的话最小的x

那么我们对所有子树大小>k的f值取max即是答案

f[i]=max j为i的儿子 (min(f[j],siz[j]/(siz[i]-1))

因为对于i的一个儿子j,假如i因为j的子树里的叛徒比例大于x而带头叛变,那么既要满足x<=(j的子树大小占i的子树大小的比例),还要满足j带头叛变即x<=f[j],所以对两个量取min

那么如果i不叛变,那么就不能满足任意一个条件,所以对所有的取max

对于叶子,f[i]=1,因为不管怎样叶子本身就是叛徒,可以视为不需要条件就可以带头叛变,即只有当x>1时才不会叛变

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<queue>
#include<map>
#include<bitset>
#include<stack>
#include<vector>
#include<set>
using namespace std;
#define MAXN 500010
#define MAXM 1010
#define INF 1000000000
#define MOD 1000000007
#define ll long long
#define eps 1e-8
struct vec{
int to;
int fro;
};
vec mp[MAXN];
int tai[MAXN],cnt;
double f[MAXN],ans=0;
int siz[MAXN];
int n,k;
inline void be(int x,int y){
mp[++cnt].to=y;
mp[cnt].fro=tai[x];
tai[x]=cnt;
}
void dfs(int x){
int i,y;
siz[x]=1;
for(i=tai[x];i;i=mp[i].fro){
y=mp[i].to;
dfs(y);
siz[x]+=siz[y];
}
if(!tai[x]){
f[x]=1;
}
if(tai[x]){
for(i=tai[x];i;i=mp[i].fro){
y=mp[i].to;
f[x]=max(f[x],min(1.0*siz[y]/(siz[x]-1),f[y]));
}
}
if(siz[x]>k){
ans=max(ans,f[x]);
}
}
int main(){
int i,x;
scanf("%d%d",&n,&k);
for(i=2;i<=n;i++){
scanf("%d",&x);
be(x,i);
}
dfs(1);
printf("%.8lf\n",ans);
return 0;
}

/*

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: