CF242D題解

Jefferyzzzz發表於2024-10-04

傳送門:https://codeforces.com/problemset/problem/242/D

對於一個點,顯然一旦達到額定值後,其他任何操作都無法使他減小,於是我們得出一個貪心性質,當且僅當一個點不合法時,才取增加他的值。同理,我們可以證明,問題必定有解,因為若一個點被選擇,必定是因為其曾不合法,選擇後使其\(+1\)合法,而若最後一個點不合法,其必定是未選擇的,選擇其則能合法。過程可以用佇列維護。時間複雜度\(O(n)\)

#include <bits/stdc++.h>

using namespace std;

inline int read() {
    char c;
    bool flag = false;
    while ((c = getchar()) < '0' || c > '9') if (c == '-') flag = true;
    int res = c - '0';
    while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + c - '0';
    return flag ? -res : res;
}

const int N = 1e5 + 10;

int head[N], cnt, a[N], b[N], step[N];

struct Edge {
    int v, next;
} e[N * 2];

void add(int u, int v) {
    e[cnt].v = v;
    e[cnt].next = head[u];
    head[u] = cnt++;
}

int main() {
    memset(head, -1, sizeof head);
    int n = read(), m = read();
    for (int i = 1; i <= m; ++i) {
        int u = read(), v = read();
        add(u, v);
        add(v, u);
    }
    for (int i = 1; i <= n; ++i) a[i] = read();
    int ans = 0;
    queue<int> q;
    for (int i = 1; i <= n; ++i) if (!a[i]) q.push(i);
    while (!q.empty()) {
        if (b[q.front()] != a[q.front()]) {
            q.pop();
            continue;
        }
        step[++ans] = q.front();
        ++b[q.front()];
        q.pop();
        for (int i = head[step[ans]]; ~i; i = e[i].next) {
            if (++b[e[i].v] == a[e[i].v]) q.push(e[i].v);
        }
    }
    printf("%d\n", ans);
    for (int i = 1; i <= ans; ++i) {
        printf("%d ", step[i]);
    }
    return 0;
}