BZOJ4726: [POI2017]Sabota?

来源:互联网 发布:ubuntu 设置apt源 编辑:程序博客网 时间:2024/06/02 05:26

一开始看这题..二分好像很兹瓷啊,虽然n有50w,但是给了20s啊,不虚啊

然后T了….

emmmmmmmmmmmm
所以还是要dp
经过观察可以发现,对于最坏的情况一定是叶子开始叛变,且如果一个人没有被他的下属们策反,他的祖先们一定也不会叛变,所以最坏情况下,叛变的点一定是一棵完整的子树
所以我们令f[i]表示以i为根的子树不叛变的情况下最小的x
f[i]=max[   min(f[j],siz[j]/(siz[i]1))   ]
最终要使所有大小>k的子树全部不叛变,所以对这些子树的f[i]取min

code:

#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<bitset>#include<string>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#include<algorithm>#define ll long long#define inf 1e9using namespace std;const int maxn = 510000;int n,k;struct edge{    int y,nex;    edge(){}    edge(const int _y,const int _nex){y=_y;nex=_nex;}}a[maxn<<1]; int len,fir[maxn];inline void ins(const int x,const int y){a[++len]=edge(y,fir[x]);fir[x]=len;}long double f[maxn];int siz[maxn];void dfs(const int x){    siz[x]=0;    for(int k=fir[x];k;k=a[k].nex)        dfs(a[k].y),siz[x]+=siz[a[k].y];    if(!siz[x]) f[x]=1.0;    else    {        f[x]=0.0;        for(int k=fir[x];k;k=a[k].nex)            f[x]=max(f[x],min((long double)siz[a[k].y]/siz[x],f[a[k].y]));    }    siz[x]++;    return;}int main(){    scanf("%d%d",&n,&k);    for(int i=2;i<=n;i++)    {        int x; scanf("%d",&x);        ins(x,i);    }    dfs(1);    long double ans=0;    for(int i=1;i<=n;i++) if(siz[i]>k)        if(f[i]>ans) ans=f[i];    printf("%.10Lf\n",ans);    return 0;}