• BZOJ 4726 [POI2017]Sabota?:树形dp


    传送门

    题意

    某个公司有 $ n $ 个人,上下级关系构成了一个有根树。其中有个人是叛徒(这个人不知道是谁)。对于一个人, 如果他下属(直接或者间接, 不包括他自己)中叛徒占的比例超过 $ x $ ,那么这个人也会变成叛徒,并且他的所有下属都会变成叛徒。你要求出一个最小的 $ x $ ,使得最坏情况下,叛徒的个数不会超过 $ k $ 。$ (1 leq k leq n leq 500000) $

    题解

    首先有一个显然的二分做法,然而不知道为什么会被卡……

    于是考虑能不能 $ O(n) $ 做。

    首先有两个结论:

    • 最坏情况下,最初的那一个叛徒一定是叶子结点。
    • 如果一个非叶子节点叛变,则它其中的一个儿子一定叛变

    所以最终所有的叛徒一定是原树中的一棵子树。

    $ f[i] $ 表示要使节点 $ i $(及其下属)恰好不能叛变的最小比例 $ x $

    因为所有 $ size[i] > k $ 的子树都不能叛变

    所以 $ ans = max(f[i]) quad (size[i] > k) $

    然后考虑怎样求 $ f[i] $

    $ f[i] $ 也等价于恰好让 $ i $ 叛变的最大比例 $ x $

    对于每一个 $ i $ ,首先枚举它的哪个子树叛变了(假设是 $ j $ )

    那么想让 $ i $ 叛变有两个条件:

    • 比例 $ x $ 满足能够让 $ j $ 叛变
    • 比例 $ x $ 满足 $ dfrac{size[j]}{size[i] - 1} > x $

    所以 $ f[i] = max(f[i], min(f[j], dfrac{size[j]}{size[i]-1})) $

    边界条件为:$ f[i] = egin{cases} 1 quad ext{叶子结点} \ 0 quad ext{非叶子节点} end{cases} $

    AC Code

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <vector>
    #define MAX_N 500005
    
    using namespace std;
    
    int n,k;
    int siz[MAX_N];
    double ans=0;
    double f[MAX_N];
    vector<int> edge[MAX_N];
    
    void read()
    {
    	scanf("%d%d",&n,&k);
    	int x;
    	for(int i=2;i<=n;i++)
    	{
    		scanf("%d",&x);
    		edge[x].push_back(i);
    	}
    }
    
    void dfs(int x)
    {
    	siz[x]=1,f[x]=(edge[x].size()==0);
    	for(int i=0;i<edge[x].size();i++)
    	{
    		int t=edge[x][i];
    		dfs(t),siz[x]+=siz[t];
    	}
    	for(int i=0;i<edge[x].size();i++)
    	{
    		int t=edge[x][i];
    		f[x]=max(f[x],min(f[t],siz[t]/(siz[x]-1.0)));
    	}
    	if(siz[x]>k) ans=max(ans,f[x]);
    }
    
    void work()
    {
    	dfs(1);
    	printf("%.9f
    ",ans);
    }
    
    int main()
    {
    	read();
    	work();
    }
    
  • 相关阅读:
    C++ const用于iterator
    C++实现类似python中的字符串split函数
    简单地解释overwrite
    ubuntu16.04 新安装的系统启动ssh服务
    强化学习7日打卡营-世界冠军带你从零实践--基于表格型方法的 RL
    spark-遇到问题小结
    Spark 读写hive 表
    spark-shell 显示乱码
    机器学习-GBDT和XGboost
    链表
  • 原文地址:https://www.cnblogs.com/Leohh/p/9096194.html
Copyright © 2020-2023  润新知