欧拉路径

图中经过所有恰好一次的路径叫欧拉路径(也就是一笔画)。如果此路径的起点和终点相同,则称其为一条欧拉回路。

求有向图字典序最小的欧拉路径。

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;
}
posted @ 2022-10-25 21:31  Network_Error  阅读(277)  评论(0)    收藏  举报