• [bzoj4027][HEOI2015]兔子与樱花_贪心_树形dp


    兔子与樱花 bzoj-4027 HEOI-2015

    题目大意:每个点有c[i]朵樱花,有一个称重m, son[i]+c[i]<=m.如果删除一个节点,这个节点的樱花或移动到它的祖先中深度最大的,且没有被删除的节点,求在满足所有点界限的情况下,最多能删除的节点数。

    注释:$1le nle 2cdot 10^6$,$1le mle 10^5$,$0le c_ile 1000$。

    想法:开始的时候很容易想到贪心,但是这东西对不对还两说

    其实仔细一想这玩意儿tm显然啊??!

    我们令c[i]+son[i]为这个点的优先级,我们显然选优先级高的。

    如果我们选了一个优先级略低的,比如说是最高优先级的..子孙?这样的话我只会是的上面的优先级哐哐往上涨直到不合法

    祖先的话删完了之后优先级高的迟早要删,这样的话底下的樱花上来就GG了。

    最后,附上丑陋的代码... ...

    #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;
    }
    

    小结:对于这种贪心的题,我们还是需要证明一下的... ...

  • 相关阅读:
    js中细小点
    被 idea 坑了的记录篇
    Spring 读写分离
    Java反射机制
    Spring AOP
    java Beanutils.copyProperties( )用法
    java List 数组删除元素
    java 中序列化(Serializable)
    webpack 入门
    使用zxing生成彩色或带图片的二维码
  • 原文地址:https://www.cnblogs.com/ShuraK/p/9277668.html
Copyright © 2020-2023  润新知