[HEOI2015]兔子与樱花

算我傻逼,看错题

对于一个节点,能选尽量选,那么选一个子节点的代价是 c[v]+lson[v]
排序贪心,树型DP即可

#include 
#include 

using namespace std;

const int SN = 2000000 + 10;

int c[SN], n, head[SN], ans, num, x, u,tmp[SN], cnt, m, s[SN];

struct Edge {
    int from,to,next;
}E[SN<<1];

void Read(int &x) {
    int in = 0,f = 1;char ch = getchar();
    while(ch<'0' || ch>'9') {if(ch=='-') f = -1;ch = getchar();}
    while(ch>='0' && ch<='9') {in = in*10+ch-'0';ch = getchar();}
    x = in*f;
}

void Add(int u,int v) {
    E[++num].from = u;
    E[num].to = v;
    E[num].next = head[u];
    head[u] = num;
}

void dfs(int u,int fa) {

    for(int i = head[u]; i; i = E[i].next) {
        int to = E[i].to;
        if(to == fa)    continue;
        dfs(to,u);
    }

    cnt = 0;
    for(int i = head[u]; i; i = E[i].next) {
        tmp[++cnt] = c[E[i].to]-1; //去掉的是点权,并且儿子数会少1
        //WA了几发,一开始直接把lson[]加到点权中
    }

    c[u] += cnt;

    sort(tmp+1,tmp+cnt+1);

    for(int i = 1; i <= cnt; i++) {
        if(c[u] + tmp[i] <= m) {
            c[u] += tmp[i];
            ans++;
        }
        else break;
    }
}

int main() {

    Read(n),Read(m);

    for(int i = 0; i < n; i++) {
        Read(c[i]);s[n] = c[i];
    }

    for(int i = 0; i < n; i++) {
        Read(x);
        for(int j = 1; j <= x; j++) {
            Read(u);
            Add(i,u);
        }
    }

    dfs(0,-1);

    printf("%d\n",ans);
    return 0;
}

你可能感兴趣的:(OI)