欧拉路径
图中经过所有边恰好一次的路径叫欧拉路径(也就是一笔画)。如果此路径的起点和终点相同,则称其为一条欧拉回路。
求有向图字典序最小的欧拉路径。
Hierholzer 算法
欧拉路径的判定
- 有向图欧拉路径(非欧拉回路):图中恰好存在 \(1\) 个点出度比入度多 \(1\)(这个点即为起点),\(1\) 个点入度比出度多 \(1\)(这个点即为终点),其余节点出度 \(=\) 入度。
- 有向图欧拉回路:所有点的入度 \(=\) 出度(起点和终点可以为任意点)。
- 无向图欧拉路径(非欧拉回路):图中恰好存在 \(2\) 个点的度数是奇数,其余节点的度数为偶数,这两个度数为奇数的点即为欧拉路径的起点和终点。
- 无向图欧拉回路:所有点的度数都是偶数(起点和终点可以为任意点)。
欧拉路径的寻找
从判定得到的起点开始 DFS,枚举每一条出边,并删掉这条边。如果一个点的所有出边都被删掉了,就把这个点压入栈内,表示这个点依赖剩余的边无法到达其他点,也就无法走到任何还未被访问过的边,这个点要在最后被访问。
#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;
#define MAXN 100010
#define MAXM 200010
int n, m, ind[MAXN], oud[MAXN], del[MAXN], cnt[2];
vector<int> e[MAXN];
stack<int> st;
void dfs(int u) {
for (int i = del[u] + 1; i < e[u].size(); i = del[u] + 1) {
del[u] = i;
dfs(e[u][i]);
}
st.push(u);
}
int main() {
cin >> n >> m;
for (int i = 1; i <= m; i++) {
int u, v;
cin >> u >> v;
e[u].push_back(v);
ind[v]++, oud[u]++;
}
for (int i = 1; i <= n; i++) del[i] = -1;
for (int i = 1; i <= n; i++) sort(e[i].begin(), e[i].end());
int s = 1;
bool flag = true;
for (int i = 1; i <= n; i++) {
if (ind[i] != oud[i])
flag = false;
if (oud[i] - ind[i] == 1) {
s = i;
cnt[0]++;
} else if (ind[i] - oud[i] == 1) cnt[1]++;
}
if (flag || (cnt[0] == 1 && cnt[1] == 1)) {
dfs(s);
while (!st.empty()) {
cout << st.top() << ' ';
st.pop();
}
}
else cout << "No" << endl;
return 0;
}

浙公网安备 33010602011771号