欧拉路、欧拉回路与哈密尔顿回路课堂笔记

图论

Posted by 周琪岳 on July 28, 2021

欧拉路径

简述

若图G中存在这样一条路径,使它恰通过G中每条边1次,则称该路径为欧拉路径。若该路径是一个圈,则称为欧拉(Euler)回路

  • 定理1:存在欧拉路的条件:图是联通的,有且仅有2个奇点。
  • 定理2:存在欧拉回路的条件:图是联通的,有0个奇点。

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

代码实现

PS:Github上tab有些时候是8格,只要粘到编辑器里就变成正常的了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>

using namespace std;

const int MAXN = 5e2 + 100;
int n, m;
int g[MAXN][MAXN];
int d[MAXN];
int cnt;
int ans[MAXN];

void dfs(int pos) {
	ans[++cnt] = pos;
	for(int i=1; i<=n; i++) {
		if(g[pos][i]) {
			g[pos][i] --;
			g[i][pos] --;
			dfs(i);
		}
	}
}

int main() {
	cin >> n >> m;
	for(int i=1, u, v; i<=m; i++) {
		cin >> u >> v;
		g[u][v] ++;
		g[v][u] ++;
		d[u] ++;
		d[v] ++;
	}
	int st = 1;
	for(int i=1; i<=n; i++) {
		if(d[i] % 2 == 1) {
			st = i;
			break;
		}
	}
	dfs(st);
	for(int i=1; i<=cnt; i++) {
		cout << ans[i] << " ";
	}
	return 0;
}

哈密尔顿回路

跟欧拉回路很像,只不过访问所有边一次变为了访问所有点一次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>

using namespace std;

const int MAXN = 1e3 + 100;
int n, m;
int g[MAXN][MAXN], ans[MAXN];
bool vis[MAXN];

bool dfs(int x, int t) {
	if(t > n) {
		if(g[x][1])
			return true;
		return false;
	}
	for(int i=1; i<=n; i++) {
		if(g[x][i] && !vis[i]) {
			ans[t] = i;
			vis[i] = true;
			if(dfs(i, t+1))
				return true;
			vis[i] = false;
		}
	}
	return false;
}

int main() {
	cin >> n >> m;
	for(int i=1, u, v; i<=m; i++) {
		cin >> u >> v;
		g[u][v] ++;
		g[v][u] ++;
	}
	ans[1] = 1;
	vis[1] = true;
	if(dfs(1, 2)) {
		for(int i=1; i<=n; i++)
			cout << ans[i] << " ";
		cout << ans[1] << endl;
	} else {
		cout << "NO";
	}
	return 0;
}

CSP-J2021rp++!!!