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;
    }
    
  • 相关阅读:
    HDU 5585 Numbers
    HDU 3308 LCIS
    POJ 2991 Crane
    POJ 1436 Horizontally Visible Segments
    POJ 3667 Hotel
    HaiHongOJ 1003 God Wang
    【SDOI 2008】 递归数列
    5月19日省中提高组题解
    【HDU 1588】 Gauss Fibonacci
    【POJ 3233】Matrix Power Series
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/9434046.html
Copyright © 2011-2022 走看看