定义
以下定义对无向图有向图 均适用。
定义图 (G = (V, E)) 的欧拉路径为:从一个点出发恰好经过所有边一次到达另一个点的一条路径。
定义图 (G = (V, E)) 的欧拉回路为:从一个点出发恰好经过所有边一次且最终回到该点的一条回路。
判定
- 对于无向图:
一张图存在欧拉回路当且仅当 所有点度数为偶数。
一张图存在欧拉路径当且仅当 所有点度数为偶数或存在恰好两个点度数为奇数。
- 对于有向图:
一张图存在欧拉回路当且仅当 所有点入度等于出度。
一张图存在欧拉路径当且仅当 所有点入度等于出度或恰好存在两个点使得一个点入度比出度多 (1) 一个点出度比入度多 (1)。
求法
首先判掉奇点个数大于 (2) 个的情况,若有奇点则任选一个奇点开始否则任选一个偶点开始。
从起始点一直向下开始 (dfs),如果走不下去了就一直回溯并将路径上的边压入栈中直到走到一个能走下去的点位置。
对于有向图来说,因为回溯是倒着方向来的,因此最后的欧拉路径也是从栈底往栈顶走的。
注意使用类似网络流的当前弧优化,复杂度 (mathcal{O}(n + m))。
常见扩展
混合图欧拉回路
给定一张混合图,请判定其是否存在欧拉回路,若存在请输出方案。
对于每条无向边,显然只会以一个方向经过,因此这个问题本质上就是需要将无向图定向使其满足有向图存在欧拉回路的判定条件。
于是我们首先先不管无向图,求出有向图给每个点带来的入度出度贡献 (in_i, out_i) 这部分是不会变的。
对于每条无向边 ((u, v)),如果定向 (u
ightarrow v) 那么对出入度的贡献为:++out[u], --in[v]
反之类似。
如果贡献只有一边,那么可以使用网络流优化全幺模矩阵线性规划的方式建模。
于是我们考虑首先给每条无向边 ((u, v)) 定好向 (u ightarrow v),于是只用考虑这条边是否反向即可,此时的贡献就只有一边了。
但需要注意的是,此时对节点的贡献即在入度上也在出度上,为了能更好地使用网络流优化全幺模矩阵的做法,我们考虑对每个点直接记录差值 (d_i = in_i - out_i)。
那么将已经定好向的无向边 ((u, v)) 反向,贡献为:d[u] += 2, d[v] -= 2
。
但此时存在系数为 (2),不为全幺模矩阵,注意到原图存在欧拉回路的 必要条件 是 (in_i, out_i) 同奇偶,于是 (d_i) 一定为偶数,那么此时我们可以一开始将 (d_i) 除以 (2) 就可以使用网络流优化全幺模矩阵线性规划了。
具体地,我们按照如下方式连边:
首先将无向边 ((u, v)) 按照 (u ightarrow v) 的方式定向,计算出这种情况下的 (d)。
-
若 (d_i > 0),我们从源点 (S ightarrow i) 连流量为 (frac{d_i}{2}) 的边。
-
若 (d_i < 0),我们从点 (i ightarrow T) 连流量为:(-frac{d_i}{2}) 的边。
-
对于原图的一条无向边 ((u, v)),我们从 (v ightarrow u) 连流量为 (1) 的边。
此时我们计算从 (S ightarrow T) 的最大流,若 (S) 连出的所有边都流满,那么有解否则无解。
若有解,我们在残余网络上确定每条无向边的方向,然后跑有向图欧拉回路构造即可。
同时,该做法可以适用于边带权的情况,只需在最大流的基础上添上费用流即可。