HEOI2015 兔子与樱花

题目传送门

这紫题……有点水


自底向上合并,每次找儿子里面最小的合并
用了vector,常数有点大,开O2才过

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define LL long long
using namespace std;
LL read() {
    LL k = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9')
        k = k * 10 + c - 48, c = getchar();
    return k * f;
}
int val[2000010];
struct zzz {
    int t, nex;
}e[2000010 << 1]; int head[2000010], tot;
void add(int x, int y) {
    e[++tot].t = y;
    e[tot].nex = head[x];
    head[x] = tot;
}
int size[2000010], n, k, ans;
bool cmp(int x, int y) {
    return val[x] < val[y];
}
void dfs(int x, int fa) {
    vector <int> q; q.clear();
    for(int i = head[x]; i; i = e[i].nex) {
        if(e[i].t == fa) continue;
		dfs(e[i].t, x); ++size[x];
        q.push_back(e[i].t);
    }
    sort(q.begin(), q.end(), cmp);
    for(int i = 0; i < q.size(); ++i) {
        if(val[q[i]] + size[q[i]] + size[x] - 1 + val[x] <= k) {
            val[x] += val[q[i]], size[x] = size[x] - 1 + size[q[i]];
            ++ans;
        }
    }
}
int main() {
    n = read(), k = read();
    for(int i = 1; i <= n; ++i) val[i] = read();
    for(int i = 1; i <= n; ++i) {
        int k = read();
        for(int j = 1; j <= k; ++j) {
            int x = read() + 1; add(i, x); add(x, i);
        }
    }
    dfs(1, 0);
    cout << ans;
    return 0;
}
posted @ 2019-11-14 11:19  MorsLin  阅读(91)  评论(0编辑  收藏  举报