找回密码
 立即注册
首页 业界区 安全 欧拉路径 & 欧拉回路

欧拉路径 & 欧拉回路

康器 2025-11-8 20:00:07
定义


  • 欧拉路径:经过连通图中所有边恰好一次的迹称为 欧拉路径
  • 欧拉回路:经过连通图中所有边恰好一次的回路称为 欧拉回路。即首尾相连的欧拉路径。
  • 欧拉图:具有欧拉回路的图称为 欧拉图
  • 半欧拉图:具有欧拉路径但不具有欧拉回路的图称为 半欧拉图
不经过重复边的途径称为
判定


  • 有向图欧拉路径:图中恰好存在 \(1\) 个点的出度比入度多 \(1\) (该点即为起点 \(S\)),\(1\) 个点的入度比出度多 \(1\) (该点即为终点 \(T\)),其余点的出度等于入度。
  • 有向图欧拉回路:图中所有点的入度等于出度(起点 \(S\) 和终点 \(T\) 可以为任意点)。
  • 无向图欧拉路径:图中恰好存在 \(2\) 个点的度数是奇数,其余点的度数为偶数,这两个度数为奇数的点即为欧拉路径的起点 \(S\) 和终点 \(T\) 。
  • 无向图欧拉回路:图中所有点的度数都是偶数(起点 \(S\) 和终点 \(T\) 可以为任意点)。
注意:存在欧拉路径的充要条件是无向图连通,有向图弱连通。
对于有向图的两点 \(u, v\) ,若将有向边改为无向边后 \(u, v\) 连通,则称 \(u, v\) 弱连通
构造

采用 Hierholzer 算法求解欧拉路径或欧拉回路。
具体地,遍历当前点 \(u\) 的所有出边 \(u \rightarrow v\)。若该边未走过,则向点 \(v\) DFS。遍历完所有出边后,将 \(u\) 加入回路。最终得到一条反向的欧拉回路,将其翻转即可。
代码实现上,有向弱连通图删边比标记边的 \(O(m^2)\) (其中 \(m\) 是边数)时间复杂度更优。可以用数组维护邻接矩阵,也可以用 vector 或链式前向星维护时间复杂度更优的邻接表。
以欧拉路径的模版题为例,要求有向弱连通图中字典序最小的欧拉路径。由于点数 \(n\) 和边数 \(m\) 均是 \(10^5\) 级别的数据,领接矩阵的 \(O(n^2)\) 的时间复杂度不可接受。考虑采用类似链表的方式记录数组 \(nxt\),其中 \(nxt_u\) 表示 \(u\) 的邻接表中下一个访问的边的编号。初始时 \(nxt_u = 0\) 即可。考虑通过排序贪心地将点的编号越小的点排在最前面,最终求得的一定是字典序最小的欧拉路径。以下代码的时间复杂度为 \(O(n + m \log m)\)。
点击查看代码[code]#include using namespace std;const int N = 1e5 + 8;int n, m, in[N], out[N], nxt[N];vector e[N];stack stk;void dfs(int u) {    for (int i = nxt; i < e.size(); i = nxt) {        nxt = i + 1;        dfs(e);    }    stk.push(u);}int main() {    cin >> n >> m;    for (int i = 1, u, v; i > u >> v;        e.push_back(v);        out++; in[v]++;    }    for (int i = 1; i > v;        e.push_back(v);        out++; in[v]++;    }    for (int i = 1; i

相关推荐

您需要登录后才可以回帖 登录 | 立即注册