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