【知识点】欧拉路径、欧拉回路与Hierholzer算法

定义

欧拉路径:图中的某条路径,将某条边恰好经过一次(可以重复经过点)。

欧拉回路:图中的某条路径,将某条边恰好经过一次的同时,满足起点和终点是同一点。

存在欧拉路径的图称为半欧拉图,存在欧拉回路的图成为欧拉图

判断

有向图 半欧拉图:图中恰好存在 $ 1 $ 个点出度比入度多 $ 1 $ (起点S),$ 1 $ 个点入度比出度多 $ 1 $ (终点T),其余节点出度与入度相等。

有向图 欧拉图:图中所有节点出度与入度相等,起终点任意

无向图 半欧拉图:图中恰好存在 $ 2 $ 个点的度数是奇数(起点和终点),其余节点度数都为偶数。

无向图 欧拉图:图中所有节点度数都为偶数,起点和终点任意

Hierholzer算法

从起点开始 $ DFS $ ,走一条边就删掉它(避免重复),走不动了再把点加入答案栈,最后倒序输出就是欧拉路径。

该算法适用于以上四种图的欧拉路径(回路)的寻找。

void dfs(int u) {
    while (!g[u].empty()) {
        int v = g[u].back();
        g[u].pop_back();
        dfs(v);
    }
    ans.push(u);
}

模板题及解法

模板题洛谷链接

解法:

#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using f64 = long double;

i64 n, m, u, v, s = -1, t = -1, rd[100100], cd[100100];
vector<i64>edge[100100];
stack<i64>ans;

bool cmp(i64 x, i64 y){
    return x > y;
}

void dfs(i64 u){
    while(!edge[u].empty()){
        v = edge[u].back();
        edge[u].pop_back();
        dfs(v);
    }
    ans.push(u);
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    cin >> n >> m;
    for(i64 i = 1;i<=m;i++)
        cin >> u >> v,
        edge[u].push_back(v),
        cd[u] ++, rd[v] ++;
    for(i64 i = 1;i<=n;i++) sort(edge[i].begin(), edge[i].end(), cmp);
    for(i64 i = 1;i<=n;i++)
        if(cd[i] == rd[i] + 1 && s == -1) s = i;
        else if(cd[i] + 1 == rd[i] && t == -1)    t = i;
        else if(cd[i] != rd[i]){
            cout << "No";
            return 0;
        }
    if(s == -1) s = 1;  //欧拉回路!
    dfs(s);
    while(!ans.empty()){
        cout << ans.top() << ' ';
        ans.pop();
    }
    return 0;
}
posted @ 2026-02-24 22:36  Alkaid16  阅读(0)  评论(0)    收藏  举报