跳转至

一本通-1341:【例题】一笔画问题(欧拉路+路径输出)

【题目描述】 如果一个图存在一笔画,则一笔画的路径叫做欧拉路,如果最后又回到起点,那这个路径叫做欧拉回路。

根据一笔画的两个定理,如果寻找欧拉回路,对任意一个点执行深度优先遍历;找欧拉路,则对一个奇点执行dfs,时间复杂度为O(m+n),m为边数,n是点数。

【输入】 第一行n,m,有n个点,m条边,以下m行描述每条边连接的两点。

【输出】 欧拉路或欧拉回路,输出一条路径即可。

【输入样例】 5 5 1 2 2 3 3 4 4 5 5 1

【输出样例】 1 5 4 3 2 1


#include <bits/stdc++.h>

using namespace std;

int vertexNum, edgeNum;
vector<vector<int> > grid;
vector<vector<bool> > visit;
vector<int> degree;
stack<int> s;

void EulerCircuit(int from)
{
    for (int to = 1; to <= vertexNum; ++to) {
        if (grid[from][to] && !visit[from][to]) {
            visit[from][to] = visit[to][from] = true;
            EulerCircuit(to);
        }
    }
    s.push(from);
}


void solve()
{
    int start = 1;
    for (int i = 1; i <= vertexNum; ++i) {
        if (degree[i] & 1) { start = i; break; }
    }

    EulerCircuit(start);

    while (!s.empty()) {
        cout << s.top() << ' ';
        s.pop();
    }
    cout << endl;
}



int main()
{
    std::ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    cin >> vertexNum >> edgeNum;
    grid.resize(vertexNum + 1, vector<int>(vertexNum + 1, 0));
    visit.resize(vertexNum + 1, vector<bool>(vertexNum + 1, false));
    degree.resize(vertexNum + 1, 0);

    for (int i = 0; i < edgeNum; ++i) {
        int from, to; cin >> from >> to;
        grid[from][to] = grid[to][from] = 1;
        ++degree[from], ++degree[to];
    }

    solve();

    return 0;
}

注意欧拉路径的输出需要用辅助栈才能正序输出。