欧拉回路
回路是起点终点为一个点的路径是回路。
图 G G G 中经过所有边一次且经过所有顶点的通路叫欧拉回路。
图 G G G 中为回路的欧拉通路为欧拉回路,图 G G G 称作欧拉图。
如果一个无向图是欧拉图,那么每个点的度数都是偶数。
如果一个有向图是欧拉图,那么每个点的入度等于出度。
dfs 实现求 欧拉通路
如果一边 dfs 一边加边是不可行的,应该 dfs 返回的过程中加边。例如下图,一条路径为 1 → 2 → 3 → 1 → 3 → 4 → 5 → 3 1 \to 2 \to 3 \to1 \to 3 \to 4 \to 5 \to 3 1→2→3→1→3→4→5→3。如果在递归时加边会出现 ( 1 , 2 ) , ( 2 , 3 ) , ( 1 , 3 ) (1,2),(2,3),(1,3) (1,2),(2,3),(1,3) 后无路可走的情况。

如果每次从头开始,会有遍历到许多走过的点,可能会被卡到
n
2
n^2
n2 所以当前弧优化,从上一走的点开始走。至此,我们得到了
O
(
n
)
O(n)
O(n) 求欧拉回路的算法。
struct edge{
int to, nxt;
}e[N];
int head[N], tot = 1;
/*
无向图通过 i / 2 得到边的编号,所以 tot 不能从 0 开始
*/
void addedge(int x, int y){
e[++tot].to = y, e[tot].nxt = head[x], head[x] = tot;
}
int eul[N];
int cnt = 0;
int vis[N];
void dfs(int x) {
for (int &i = head[x]; i; i = e[i].nxt) { //当前弧度
int y = e[i].to;
if (vis[i / 2]) continue; //无向图两倍边
vis[i / 2] = 1;
dfs(y);
}
eul[++cnt] = x; //返回时记录
}
int main() {
int n = read(), m = read();
for (int i = 1; i <= m; i++){
int x = read(), y = read();
addedge(x, y); addedge(y, x);
}
dfs(1);
for (int i = cnt; i; i--) printf("%d ", eul[i]); //倒序
return 0;
}

浙公网安备 33010602011771号