1 条题解

  • 0
    @ 2025-8-24 22:38:37

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar JCY_
    Nothing is wasted

    搬运于2025-08-24 22:38:37,当前版本为作者最后更新于2022-09-13 11:37:25,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    可能更好的阅读体验

    题目大意

    给你一个 nn 个点 mm 条边的有向图,从 00 开始标号,有重边,有自环(n104,m2×105n\leq 10^4,m\leq 2\times 10^5),每个点有三种状态 0,12,10,\frac{1}{2},1

    考察点 uu,设在其所有前驱 vv 中,有 c0c_0 个点状态为 00c1c_1 个点状态为 11c2c_2 个点状态为 12\frac{1}{2}。若 c0>c1c_0>c_1 则点 uu 状态为 00,若 c0<c1c_0<c_1 则点 uu 状态为 11,否则点 uu 状态为 12\frac{1}{2}

    现已知点 00 的状态为 00,点 11 的状态为 11,且这两个点入度均为 00。求在所有符合上述规则的状态分配中,状态均相同的点的标号,以及它们的状态。

    分析

    一眼看上去直接做有些困难,不妨考虑求出每个点状态大小的上界和下界,若上下界相同则说明其为所求点。上下界求法理应相同,所以只考虑如何求出下界。

    先将点 11 的状态赋为 11,其它点赋为 00。将点 11 入队,然后开始进行类似 BFS 的调整:取出队首 uu,遍历其所有后继 vv,若此时 vv 的状态不符合规则,则修改 vv 的状态并将其入队。

    正确性可以感性理解,因为每次调整都是必须的。

    考虑分析这一过程的复杂度,不难发现每个点入队时状态大小必然变大,因此每个点入队不超过 22 次,复杂度为 O(m)O(m)

    具体实现细节见代码。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 1e4 + 10;
    int n, in[MAXN], c[MAXN][3], val0[MAXN], val1[MAXN], hd, tl, qu[MAXN * 2];
    vector<int> g[MAXN];
    inline int calc(int x) {
        if (c[x][0] > c[x][1]) return 0;
        if (c[x][1] > c[x][0]) return 1;
        return 2;
    }
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        cin >> n;
        for (int i = 2; i < n; ++i) {
            cin >> in[i];
            for (int j = 0, x; j < in[i]; ++j) {
                cin >> x;
                g[x].emplace_back(i);
            }
        }
        for (int i = 0; i < n; ++i) c[i][0] = in[i];
        val0[1] = 1;
        for (auto v : g[1]) --c[v][0], ++c[v][1];
        qu[hd = tl = 1] = 1;
        while (hd <= tl) {
            int u = qu[hd++];
            for (auto v : g[u]) {
                int t = calc(v);
                if (val0[v] != t) {
                    for (auto w : g[v]) {
                        --c[w][val0[v]];
                        ++c[w][t];
                    }
                    qu[++tl] = v;
                    val0[v] = t;
                }
            }
        }
        for (int i = 0; i < n; ++i) {
            c[i][1] = in[i];
            c[i][0] = c[i][2] = 0;
        }
        fill(val1 + 1, val1 + n, 1);
        val1[0] = 0;
        for (auto v : g[0]) --c[v][1], ++c[v][0];
        qu[hd = tl = 1] = 0;
        while (hd <= tl) {
            int u = qu[hd++];
            for (auto v : g[u]) {
                int t = calc(v);
                if (val1[v] != t) {
                    for (auto w : g[v]) {
                        --c[w][val1[v]];
                        ++c[w][t];
                    }
                    qu[++tl] = v;
                    val1[v] = t;
                }
            }
        }
        for (int i = 0; i < n; ++i) {
            if (val0[i] == val1[i]) {
                if (val0[i] == 2) {
                    cout << "1/2";
                } else {
                    cout << val0[i];
                }
            } else {
                cout << '?';
            }
            cout << '\n';
        }
        return 0;
    }
    • 1

    信息

    ID
    7729
    时间
    1000ms
    内存
    128MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者