zoukankan      html  css  js  c++  java
  • [BZOJ4027][HEOI2015]兔子与樱花

    bzoj
    luogu

    description

    一棵(n)个点的树,每个点上有一个权值(c_i)。你可以删掉任意一个除根之外的节点,删除后这个点的权值和儿子都会转移到它的父亲上去。每个点需要满足(c_i+son(i)le m),其中(son(i))(i)节点的儿子个数。求最多可以删掉多少个点。
    (nle2 imes10^6)

    sol

    (f_i)表示(i)点子树内最多可以删多少个点,(g_i)表示在(i)子树内达成最优策略时,(i)号点的(c_i+son(i))是多少。
    对于一个点(u),考虑它的所有儿子删还是不删。一个贪心的结论是:按照(g_v)从小到大能删则删。因为删除一个儿子(v)只会增大(u)(g_u)导致(u)可能删不掉,所以这样删一定是不会使答案更劣的。

    code

    辣鸡(mbox{bzoj})不支持(mbox{-std=c++11})

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    using namespace std;
    int gi(){
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    const int N = 2e6+5;
    int n,m,f[N],g[N],tmp[N];
    vector<int>edge[N];
    void dfs(int u){
    	for (auto v:edge[u]) dfs(v),f[u]+=f[v];
    	int len=0;
    	for (auto v:edge[u]) tmp[++len]=g[v]-1;
    	sort(tmp+1,tmp+len+1);
    	for (int i=1;i<=len;++i) if (g[u]+tmp[i]<=m) g[u]+=tmp[i],++f[u];
    }
    int main(){
    	n=gi();m=gi();
    	for (int i=1;i<=n;++i) g[i]=gi();
    	for (int i=1;i<=n;++i){
    		int k=gi();g[i]+=k;
    		while (k--) edge[i].push_back(gi()+1);
    	}
    	dfs(1);printf("%d
    ",f[1]);
    	return 0;
    }
    
  • 相关阅读:
    jdbc的入门学习
    java代码生成Excel文件3000条自定义属性的的域账户名
    java面试题
    node图片资源捉取
    运用node真机调试移动web项目
    node读取文件转换json文件
    微信小程序页面导航功能
    JavaScript值全等判断
    微信小程序海报生成功能
    JavaScript常用数组操作方法,包含ES6方法
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/9434046.html
Copyright © 2011-2022 走看看