[ SHOI 2015 ] 零件组装机

题目

Luogu
LOJ
Acwing

思路

001.png 002.png

代码

貌似在 \(Acwing\) 上要吸臭氧

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
const int N = 100010;
set<int> G[N];
int T, fa[N], id[N], sz[N], cnt, now;
bool cmp(int a, int b) { return sz[a] < sz[b]; }
inline bool check(int a, int b, int c, int d) {
    int n = b - a + 1, m = d - c + 1;
    if (n > m) return false;
    for (int i = 0; i < m; i++) {
        int x = a + i % n, y = c + i;
        if (G[y].find(x) == G[y].end()) return false;
        else now++;
    }
    return true;
}
int main() {
    cin >> T;
    for (int n, m; T--; ) {
        scanf("%d%d", &n, &m);
        for (int i = 0; i < n; i++) G[i].clear();
        memset(fa, 0, sizeof fa), memset(sz, 0, sizeof sz);
        cnt = 0, now = 0;
        bool flag = true;
        for (int a, b; m--; ) {
            scanf("%d%d", &a, &b);
            if (a > b) swap(a, b);
            if (a == b || G[b].find(a) != G[b].end()) flag = false;
            else G[b].insert(a), cnt++; // 这里反着连边
        }
        for (int i = 1; i < n && flag; i++) {
            if (G[i].empty()) flag = false;
            else fa[i] = *G[i].rbegin();
        }
        for (int i = 0; i < n; i++) sz[i] = 1;
        for (int i = n - 1; i >= 1; i--) sz[fa[i]] += sz[i];
        for (int i = 0; i < n; i++) id[i] = i;
        sort(id, id + n, cmp);
        for (int i = 0; i < n - 1 && flag; i++) {
            int u = fa[id[i]], v = id[i];
            if (!check(u, v - 1, v, v + sz[v] - 1)) flag = false;
        }
        if (flag && cnt == now) cout << "YES" << endl;
        else cout << "NO" << endl;
    }
    return 0;
}
posted @ 2021-06-17 16:23  Protein_lzl  阅读(55)  评论(0编辑  收藏  举报