【题目描述】
如果一个图存在一笔画,则一笔画的路径叫做欧拉路,如果最后又回到起点,那这个路径叫做欧拉回路。
根据一笔画的两个定理,如果寻找欧拉回路,对任意一个点执行深度优先遍历;找欧拉路,则对一个奇点执行dfs,时间复杂度为O(m+n),m为边数,n是点数。
【输入】
第一行n,m,有n个点,m条边,以下m行描述每条边连接的两点。
【输出】
欧拉路或欧拉回路,输出一条路径即可。
【输入样例】
5 5
1 2
2 3
3 4
4 5
5 1
【输出样例】
1 5 4 3 2 1
分析
- 首先我们要知道什么是欧拉回路,什么是欧拉路;欧拉回路有0个奇点,欧拉路有2个奇点(两个定理)(起点是一个奇点,终点是另一个奇点);(欧拉回路和欧拉路,都要保证图是连通的)
- 所以我们要知道什么是奇点,奇点就是这个点的入度(出度)为奇数,那么就是奇点(奇点就是从这个点出发的线有奇数条,偶点就是从这个点出发的线有偶数条。)
- 所以用一个dis数组去记录每个节点的度数,然后找奇点start,如果有奇点(start!=1)的话,从奇点出发到可另一个奇点(欧拉路);无奇点的话,从第一个结点(start默认=1)出发(欧拉回路);
- 正如题上所说:找欧拉回路,对任意一个点执行深度优先遍历,找欧拉路,则对一个奇点执行dfs;
#include <bits/stdc++.h>
using namespace std;
const int N = 1000;
int a[N][N];//存图
int dis[N];//表示结点的度
int path[N];//记录路径
int n, m, cnt;
//欧拉路2个奇点,欧拉回路0个奇点
void dfs(int u) {
//从当前点u分别向其他n个点发起搜索
for (int i = 1; i <= n; ++i) {
if (a[u][i]) {
//一笔画,一路到底 不存在回溯
a[u][i] = a[i][u] = 0;
dfs(i);
}
}
path[++cnt] = u;
}
int main() {
cin.tie(0);
cin >> n >> m;
for (int i = 0; i < m; ++i) {
int x, y;
cin >> x >> y;
a[x][y] = a[y][x] = 1;
dis[x]++;
dis[y]++;
}
int start = 1;
for (int i = 1; i <= n; ++i) {
//找奇点
if (dis[i] % 2)
start = i;
}
//有奇点(start!=1)的话,从奇点出发到可另一个奇点(欧拉路);
//无奇点的话,从第一个结点(start默认=1)出发(欧拉回路);
dfs(start);
for (int i = 1; i <= cnt; ++i) {
cout << path[i] << " ";
}
return 0;
}