[bzoj4726]Sabota

做的题太少,什么都要看题解..

题意只给出一个叛徒,则他一定是叶子结点(最坏情况下),那么“带头反叛”的点一定构成了一条链。

令f[u]表示u不带头反叛的最小值,则考虑它的每一支儿子v,(不反叛)f[v],(反叛)size[v]/(size[u]-1),这里取一个min。

因为是最坏情况,所以对所有儿子取max。

现在来考虑答案如何构造(这个我写完想了很久),对于std中ans=max(ans,f[u])的做法(size[u]>k),

先证必要性:显然,每一棵size大于K的子树,我们不能取满,ans至少要达到f[u]。

再证充分性:我们只是对每一棵size大于K的子树进行了询问。也许它们f[u]中的选择是不合法的,却不会影响答案;再者,最开始到达K的子树一定不能带头反叛,那么它就不需要再对上进行转移。所以严格来讲某题解的std还少了一句话【已经标记】,只是不知道为何能过。(也许不写也是正确的吧,牵扯到一堆不等式,反正我证不出来)

#include<cstdio>
#include<algorithm>
#define eps 1e-8
#define N 1000010
using namespace std;
int edgenum,n,K;
int vet[N],head[N],size[N],son[N],next[N];
double f[N];
double ans=0;
void add(int u,int v){
    edgenum++;vet[edgenum]=v;next[edgenum]=head[u];head[u]=edgenum;
}
void dfs(int u){
    int e=head[u];size[u]=1;son[u]=0;
    while(e>0){
        int v=vet[e];
        dfs(v);
        son[u]+=size[v];size[u]+=size[v];
        e=next[e];
    }
    e=head[u];if(e==0){
        f[u]=1.0;
        if(size[u]>K)ans=max(ans,f[u]);
        return;
    }
    while(e>0){
        int v=vet[e];
        if(size[v]>K){e=next[e];continue;}///////////That‘s it!
        f[u]=max(f[u],min(f[v],1.0*size[v]/(size[u]-1)));
        e=next[e];
    }
    if(size[u]>K){
        ans=max(ans,f[u]);
    }
}
int main()
{
    scanf("%d%d",&n,&K);
    for(int i=2;i<=n;i++){
        int x;scanf("%d",&x);
        add(x,i);
    }
    dfs(1);
    printf("%.10lf",ans);
}

bzoj4726

时间: 2024-12-14 03:20:09

[bzoj4726]Sabota的相关文章

【BZOJ4726】[POI2017]Sabota? 树形DP

[BZOJ4726][POI2017]Sabota? Description 某个公司有n个人, 上下级关系构成了一个有根树.其中有个人是叛徒(这个人不知道是谁).对于一个人, 如果他 下属(直接或者间接, 不包括他自己)中叛徒占的比例超过x,那么这个人也会变成叛徒,并且他的所有下属都会变 成叛徒.你要求出一个最小的x,使得最坏情况下,叛徒的个数不会超过k. Input 第一行包含两个正整数n,k(1<=k<=n<=500000). 接下来n-1行,第i行包含一个正整数p[i+1],表示

[bzoj4726][POI2017][Sabota?] (树形dp)

Description 某个公司有n个人, 上下级关系构成了一个有根树.其中有个人是叛徒(这个人不知道是谁).对于一个人, 如果他 下属(直接或者间接, 不包括他自己)中叛徒占的比例超过x,那么这个人也会变成叛徒,并且他的所有下属都会变 成叛徒.你要求出一个最小的x,使得最坏情况下,叛徒的个数不会超过k. Input 第一行包含两个正整数n,k(1<=k<=n<=500000). 接下来n-1行,第i行包含一个正整数p[i+1],表示i+1的父亲是p[i+1](1<=p[i+1]&

bzoj4726【POI2017】Sabota?

首先可以推出来如果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[

bzoj4726 [ POI2017 ] -- 树形DP

显然: 1.最坏情况下最初的叛徒一定是叶子. 2.若x不是叛徒,那么x的父亲也不是叛徒. 令f[i]表示i不是叛徒的最小x,s[i]表示i的子树大小,那么答案就是所有s[i]>k的f[i]的最大值. 接下来考虑怎么求f[i]. 当i是叶子节点时,因为每个叶子节点都有可能是叛徒,所以f[i]应是1,表示只有f[i]>1时可行. 当i不是叶子节点时,枚举每个子节点j. 当j是叛徒时,f[i]>s[j]/(s[i]-1) 当j不是叛徒时,f[i]>f[j] 所以可以用min(s[j]/(

BZOJ 4726 POI 2017 Sabota? 树形DP

4726: [POI2017]Sabota? Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 128  Solved: 49[Submit][Status][Discuss] Description 某个公司有n个人, 上下级关系构成了一个有根树.其中有个人是叛徒(这个人不知道是谁).对于一个人, 如果他下属(直接或者间接, 不包括他自己)中叛徒占的比例超过x,那么这个人也会变成叛徒,并且他的所有下属都会变成叛徒

[POI2017]Sabota【观察+树形Dp】

Online Judge:Bzoj4726 Label:观察,树形Dp,水题 题目描述 某个公司有n个人, 上下级关系构成了一个有根树.公司中出了个叛徒(这个人不知道是谁). 对于一个人, 如果他下属(直接或者间接, 不包括他自己)中叛徒占的比例超过x,那么这个人也会变成叛徒,并且他的所有下属都会变成叛徒. 你要求出一个最小的x,使得最坏情况下,叛徒的个数不会超过k. 输入 第一行包含两个正整数n,k(1<=k<=n<=500000). 接下来n-1行,第i行包含一个正整数p[i+1],

BZOJ 4726: [POI2017]Sabota?

Description 给一棵树,求最小的一个比例使得是叛徒的人数不超过k. Sol 树形DP. 一开始直接写了个二分...然后T了...复杂度应该挺科学...但是常数大... 然后看见了树形DP的做法... Code /************************************************************** Problem: 4726 User: BeiYu Language: C++ Result: Accepted Time:12456 ms Memor

BZOJ_4726_[POI2017]Sabota?_树形DP

Description 某个公司有n个人, 上下级关系构成了一个有根树.其中有个人是叛徒(这个人不知道是谁).对于一个人, 如果他 下属(直接或者间接, 不包括他自己)中叛徒占的比例超过x,那么这个人也会变成叛徒,并且他的所有下属都会变 成叛徒.你要求出一个最小的x,使得最坏情况下,叛徒的个数不会超过k. Input 第一行包含两个正整数n,k(1<=k<=n<=500000). 接下来n-1行,第i行包含一个正整数p[i+1],表示i+1的父亲是p[i+1](1<=p[i+1]&

[POI2017]bzoj4726 Sadota?

题目描述 离线题库请 题目描述 某个公司有\(n\)个人, 上下级关系构成了一个有根树.其中有个人是叛徒(这个人不知道是谁).对于一个人, 如果他 下属(直接或者间接, 不包括他自己)中叛徒占的比例超过\(x\),那么这个人也会变成叛徒,并且他的所有下属都会变 成叛徒.你要求出一个最小的\(x\),使得最坏情况下,叛徒的个数不会超过\(k\). 输入格式 第一行包含两个正整数\(n,k(1<=k<=n<=500000)\). 接下来\(n-1\)行,第\(i\)行包含一个正整数\(p[i