QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#189036#6861. Counter StrikejrjyyAC ✓413ms40704kbC++204.8kb2023-09-26 19:41:592023-09-26 19:41:59

Judging History

你现在查看的是最新测评结果

  • [2023-09-26 19:41:59]
  • 评测
  • 测评结果:AC
  • 用时:413ms
  • 内存:40704kb
  • [2023-09-26 19:41:59]
  • 提交

answer

#include <bits/stdc++.h>

using i64 = long long;

struct DSU {
    std::vector<int> fa, sz;
    DSU(int n = 0) { init(n); }
    void init(int n) {
        fa.resize(n), std::iota(fa.begin(), fa.end(), 0);
        sz.assign(n, 1);
    }
    int find(int x) {
        while (x != fa[x]) x = fa[x] = fa[fa[x]];
        return x;
    }
    bool same(int x, int y) { return find(x) == find(y); }
    bool merge(int x, int y) {
        if ((x = find(x)) == (y = find(y))) return false;
        return sz[x] += sz[y], fa[y] = x, true;
    }
    int size(int x) { return sz[find(x)]; }
};

struct BlockCutTree {
    int n;
    std::vector<std::vector<int>> adj;
    std::vector<int> dfn, low, stk;
    int cur, cnt;
    std::vector<std::pair<int, int>> edges;

    BlockCutTree(int n_ = 0) {
        init(n_);
    }

    void init(int n_) {
        n = n_;
        adj.assign(n, {});
        dfn.assign(n, -1);
        low.resize(n);
        stk.clear();
        cur = cnt = 0;
        edges.clear();
    }

    void addEdge(int u, int v) {
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    void dfs(int u) {
        dfn[u] = low[u] = cur++;
        stk.push_back(u);
        for (auto v : adj[u]) {
            if (dfn[v] == -1) {
                dfs(v);
                low[u] = std::min(low[u], low[v]);
                if (low[v] == dfn[u]) {
                    for (int x = -1; x != v; stk.pop_back()) {
                        x = stk.back();
                        edges.emplace_back(n + cnt, x);
                    }
                    edges.emplace_back(u, n + cnt++);
                }
            } else {
                low[u] = std::min(low[u], dfn[v]);
            }
        }
    }

    std::pair<int, std::vector<std::pair<int, int>>> work(int rt = 0) {
        dfs(rt);
        return {cnt, edges};
    }
};

void solve() {
    int n, m, k;
    std::cin >> n >> m >> k;

    std::vector<std::vector<int>> adj(n);
    for (int i = 0; i < m; ++i) {
        int u, v;
        std::cin >> u >> v;
        --u, --v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    std::vector<int> a(k);
    for (auto &u : a) {
        std::cin >> u;
        --u;
    }

    std::vector<bool> vis;
    DSU dsu(n);
    std::vector<std::vector<int>> s(n);
    int dcnt = -1;
    auto work = [&](int del) {
        vis.assign(n, true);
        dsu.init(n);
        s.assign(n, {});
        dcnt = 0;

        for (auto u : a) {
            vis[u] = false;
            s[u] = {u};
        }
        if (del != -1) {
            vis[del] = false;
        }

        auto merge = [&](int u, int v) {
            if (!vis[u] || !vis[v]) {
                return;
            }
            u = dsu.find(u), v = dsu.find(v);
            if (u == v) {
                return;
            }
            dcnt -= (s[u].size() >= 2) + (s[v].size() >= 2);
            s[u].insert(s[u].end(), s[v].begin(), s[v].end());
            dcnt += (s[u].size() >= 2);
            dsu.merge(u, v);
        };

        for (int u = 0; u < n; ++u) {
            for (auto v : adj[u]) {
                merge(u, v);
            }
        }

        for (int i = k - 1; i >= 0; --i) {
            int u = a[i];
            if (u == del) {
                continue;
            }
            vis[u] = true;
            for (auto v : adj[u]) {
                merge(u, v);
            }

            if (s[u].size() >= 3 || dcnt >= 1 + (del == -1)) {
                return i;
            }
        }

        return -1;
    };

    int ans = work(-1), x = a[ans];
    if (dcnt >= 2 || ans == -1) {
        std::cout << ans + 1 << "\n";
        return;
    }

    BlockCutTree g(n);
    for (int u = 0; u < n; ++u) {
        for (auto v : adj[u]) {
            if (vis[u] && vis[v] && u < v) {
                g.addEdge(u, v);
            }
        }
    }
    auto [cnt, edges] = g.work(x);
    std::vector<std::vector<int>> e(n + cnt);
    for (auto [u, v] : edges) {
        e[u].push_back(v);
        e[v].push_back(u);
    }

    int y = s[x][1], z = s[x][2], del = -1;
    auto dfs = [&](auto self, int u, int fa) -> int {
        int c = u == y || u == z;
        for (auto v : e[u]) {
            if (v == fa) {
                continue;
            }
            c += self(self, v, u);
        }
        if (c == 2 && del == -1) {
            del = u;
        }
        return c;
    };
    dfs(dfs, x, -1);

    if (del >= n) {
        std::cout << ans + 1 << "\n";
        return;
    }

    ans = std::min(ans, work(del));

    std::cout << ans + 1 << "\n";
}

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);

    int t;
    std::cin >> t;

    while (t--) {
        solve();
    }

    return 0;
}

详细

Test #1:

score: 100
Accepted
time: 413ms
memory: 40704kb

input:

4446
21 23 21
21 20
19 10
6 11
9 21
18 9
14 1
18 11
14 2
19 15
17 11
6 2
19 17
3 16
1 7
5 11
17 4
10 20
13 16
13 3
13 8
9 11
12 13
12 18
12 3 13 4 10 11 6 1 14 9 15 21 8 19 18 5 16 17 7 20 2
24 28 24
19 15
2 11
20 18
19 17
8 6
3 10
21 18
22 6
21 10
14 6
14 7
5 19
2 23
5 10
1 11
12 20
13 16
24 3
10 9...

output:

12
19
8
4
5
2
15
12
12
18
13
13
4
6
10
11
7
13
15
12
11
0
5
0
11
10
3
0
12
1
15
15
12
11
11
7
13
7
15
12
8
14
4
6
12
11
0
17
18
16
1
1
15
11
6
10
12
18
11
3
2
11
9
12
0
5
16
3
11
15
11
14
12
14
0
15
12
16
9
14
15
10
1
18
11
4
3
0
8
11
11
11
19
16
12
13
19
0
7
11
15
5
14
0
14
4
13
2
8
12
12
0
17
16
1...

result:

ok 4446 lines