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

    传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=4027

    思路:自底向上贪心。

    设f[i]表示i的子树中最多能删多少点,

    g[i]表示i的子树删去f[i]个点后的重量。

    每次给儿子按g[son[i]]排序,贪心地从小到大删,直到不能删。

    为什么可以这样做?

    因为删下面的比删上面的点不会更差,

    如果因为按贪心删了儿子而导致这个点不能再删,那么我们只会损失一个点,就是该点。

    而删除儿子至少会删除一个,所以不会亏。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    const int maxn=2000010,maxm=maxn<<1;
    using namespace std;
    int n,m,pre[maxm],now[maxn],son[maxm],tot,c[maxn],a[maxn],ans;
    bool ok;char ch;
    void read(int &x){
    	for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
    	for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    	if (ok) x=-x;
    }
    void add(int a,int b){pre[++tot]=now[a],now[a]=tot,son[tot]=b;}
    void dfs(int x){
    	for (int y=now[x];y;y=pre[y]) dfs(son[y]);
    	int cnt=0;
    	for (int y=now[x];y;y=pre[y]) a[++cnt]=c[son[y]];
    	sort(a+1,a+1+cnt);
    	for (int i=1;i<=cnt;i++){
    		if (c[x]+a[i]-1>m) break;
    		c[x]+=(a[i]-1),ans++;
    	}
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++) read(c[i]);
    	for (int i=1,x,num;i<=n;i++){
    		read(num),c[i]+=num;
    		for (int j=1;j<=num;j++) read(x),x++,add(i,x);
    	}
    	dfs(1),printf("%d
    ",ans);
    	//for (int i=1;i<=n;i++) printf("%d %d %d
    ",i,f[i],g[i]);
    	return 0;
    }
    


  • 相关阅读:
    Spring之Condition(二)在哪里解析的
    SpringBoot启动跟代码过程
    Spring之Condition(一)
    Kafka之 vm.max_map_count
    Redis常见面试题
    Redis为什么快
    TCP一个包多大
    场景问题
    这是一个测试
    小程序-使用django-drf开接口的步骤
  • 原文地址:https://www.cnblogs.com/thythy/p/5493503.html
Copyright © 2011-2022 走看看