1 条题解

  • 0
    @ 2026-10-26 21:53:09

    思路与算法

    无向图检查非零度顶点连通及所有度数为偶;有向图检查入度等于出度并覆盖全部非零度边。选择有边起点,显式栈Hierholzer消耗唯一边号,退栈收集后逆序输出。无向边反向经过时取负编号。

    正确性说明

    度条件是欧拉回路必要条件;在非零度部分连通的条件下也充分。有向平衡且弱连通时所有有边部分属于同一可行欧拉结构。Hierholzer每次用未用边延伸,局部闭游走在退栈时拼成全局回路;检查最终恰有m边也同时排除分离的回路。

    复杂度

    读入、度数组和游标初始化O(n+m),每个邻接项扫描一次,总O(n+m)时间与空间。

    易错点

    孤点不影响有边部分;m=0输出YES及空方案。自环无向度数增加2,重边用不同编号。特判验证符号、连续性、闭合及每边恰一次,不能固定比较样例路径。

    参考代码(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int t, n, m;
        cin >> t >> n >> m;
        vector<vector<pair<int, int>>> g(n);
        vector<int> in(n), out(n);
        for (int i = 1, u, v; i <= m; i++) {
            cin >> u >> v;
            --u;
            --v;
            g[u].push_back({v, i});
            out[u]++;
            in[v]++;
            if (t == 1) {
                g[v].push_back({u, -i});
                out[v]++;
                in[u]++;
            }
        }
        for (int i = 0; i < n; i++)
            if ((t == 1 && out[i] % 2) || (t == 2 && out[i] != in[i])) {
                cout << "NO\n";
                return 0;
            }
        int root = 0;
        while (root < n && !out[root])
            root++;
        if (root == n) {
            cout << "YES\n\n";
            return 0;
        }
        vector<int> used(m + 1), pos(n), st(1, root), edge, ans;
        while (!st.empty()) {
            int u = st.back();
            while (pos[u] < (int)g[u].size() && used[abs(g[u][pos[u]].second)])
                pos[u]++;
            if (pos[u] < (int)g[u].size()) {
                auto e = g[u][pos[u]++];
                used[abs(e.second)] = 1;
                st.push_back(e.first);
                edge.push_back(e.second);
            } else {
                st.pop_back();
                if (!edge.empty()) {
                    ans.push_back(edge.back());
                    edge.pop_back();
                }
            }
        }
        if ((int)ans.size() != m) {
            cout << "NO\n";
            return 0;
        }
        reverse(ans.begin(), ans.end());
        cout << "YES\n";
        for (int i = 0; i < m; i++)
            cout << ans[i] << (i + 1 == m ? '\n' : ' ');
    }
    
    • 1

    信息

    ID
    1869
    时间
    1000ms
    内存
    256MiB
    难度
    普及
    标签
    递交数
    0
    已通过
    0
    上传者