【知识点】欧拉路径、欧拉回路与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;
}

浙公网安备 33010602011771号