欧拉回路

回路是起点终点为一个点的路径是回路。

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 12313453。如果在递归时加边会出现 ( 1 , 2 ) , ( 2 , 3 ) , ( 1 , 3 ) (1,2),(2,3),(1,3) (1,2),(2,3),(1,3) 后无路可走的情况。

欧拉回路_第1张图片
如果每次从头开始,会有遍历到许多走过的点,可能会被卡到 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;
}

你可能感兴趣的:(欧拉回路)