Greedy A-Bunny and Sakura

Bunny and cherry blossoms

Rabbit and cherry blossom original title
Insert picture description here

answer

Ideas

Need to ask for the maximum number of nodes that can be deleted.

We start deleting from the leaf node. Why not start from another node? Assuming that we don’t start from a leaf node, then every deletion needs to consider the weight of the node’s parent node and the weight of the node and the number of child nodes. If we start from the leaf node, we only need to consider the weight of the node and its parent node. The weight can be. Relatively simple.

If the number of leaf nodes to be deleted is the most, the weight of the deleted node needs to be as small as possible. In this way, the weight concentrated on its parent node will be as small as possible, and the number of nodes that can be deleted will increase.

achieve

First, to find leaf nodes, you can use depth-first search.
After that, you need to delete the current smallest weight every time, you can use sorting or priority queue.

AC code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<string>
#include<queue>
#include<map>
#include<stack>
#include<list>
#include<set>
#include<deque>
#include<vector>
#include<ctime>

using namespace std;
//#pragma GCC optimize(2)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define ull unsigned long long
#define ll long long
#define rep(i, x, y) for(int i=x;i<=y;i++)
#define mms(x, n) memset(x, n, sizeof(x))
#define mmc(a, b) memcpy(a, b, sizeof(b))
#define INF (0x3f3f3f3f)
#define mod (ull)(1e9+7)
typedef pair<int, int> P;

namespace FastIO {
    const int bufsiz = 1 << 22;
    char buf[bufsiz];

    inline char getch() {
        static int tot;
        tot++;
        if (tot == bufsiz) {
            fread(buf, 1, bufsiz, stdin);
            tot = 0;
        }
        return buf[tot];
    }

    inline int read() {
        int x = 0;
        char c = getch();
        while (!isdigit(c))c = getch();
        while (isdigit(c))x = x * 10 + c - '0', c = getch();
        return x;
    }
}
using FastIO::read;
// 洛谷的该题不用快读会TLE。
const int N = 2e6 + 10;
int c[N];
vector<int> son[N];
int ans;
int n, m;

bool cmp(int a, int b) {
    return c[a] < c[b];
}

void dfs(int node) {
    if (son[node].empty()) return;
    int size = son[node].size();
    for (int i = 0; i < size; i++) {
//        int nNode = ;
        dfs(son[node][i]);
    }
    sort(son[node].begin(), son[node].end(), cmp);
    for (int i = 0; i < size; i++) {
        int x = c[node] - 1 + c[son[node][i]];
        if (x <= m) {
            ans++;
            c[node] = x;
            // 这里有个Tips。
            // 存在情况:该节点的子节点有子节点。
            // 开始我做的时候把每个子节点的子节点都挪到了当前节点,并且在循环中对每个新增的节点都判断是否能够移动到当前节点。
            // 其实是完全不必要的。在我们删除了子节点之后,其权重会增加到当前节点,而既然在该子节点作为父节点时,并没有删除其子节点,说明删除后该子节点的权重加上其子节点的数量会超载。在删除了该子节点后,父节点拥有了其权重,父节点的权重加上被删节点的子节点的数量大于等于被删节点的权重加上子节点的数量,必然超载,所以不能对子节点进行删除。
        } else break;
    }
}

int main() {
    n = read(), m = read();
//    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; i++) {
//        scanf("%d", &c[i]);
        c[i] = read();
    }
    for (int i = 0; i < n; i++) {
        int size;
//        scanf("%d", &size);
        size = read();
        c[i] += size;
        while (size--) {
            int tmp = read();
//            scanf("%d", &tmp);
            son[i].push_back(tmp);
        }
    }
    dfs(0);
    printf("%d", ans);
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_45934120/article/details/107638557