算法 {
欧拉回路(有向图)
定义
#欧拉回路#
给定有向图G, 如果存在一个环x->...->x
满足G
中所有的边 都存在于这个环中一次, 那么这个环 称之为欧拉回路;
.
比如G: a<->b<->c
, 那么a->b->c->b->a
是一个欧拉回路;
#欧拉回路图#
存在欧拉回路的图, 称之为欧拉回路图;
.
结论: 有向图G, 如果{每个点的入度等于出度 | 所有边是连通的}, 那么G是欧拉回路图;
性质
算法
求欧拉回路路径
比如a->b->c->a, b->b
, 那么a->b->b->c->a
是一个欧拉回路, 你需要依次输出每条边的ID号;
做法是: 暴力DFS, 比如当前是dfs(a)
对于a->b
这个边 (令她的ID是X
), 我们先把这个边给删除掉 (即让FirstEdge[a] = NextEdge[ X]
), 然后dfs(b)
, 最后回溯时 再ANS.push_back(X)
; DFS结束后 reverse(ANS)
一下;
拿上面例子来说, 比如dfs次序: a1, b1, c, a2, b2
, 在c
这里回溯时 我们将c->a
放入答案, 然后在b1
回溯时 放入了b->c
, 然后在b1
回溯了b->b
, 最后在a1
回溯了a->b
;
auto Dfs = [&]( auto & _dfs, int _cur)->void{
for( ;_graph.FirstEdge[ _cur] != -1; ){
auto edgeID = _graph.FirstEdge[ _cur];
auto nex = _graph.DirectedEdges.at( edgeID).EndPoint;
_graph.FirstEdge[ _cur] = _graph.NextEdge[ edgeID];
_dfs( _dfs, nex);
ANS.push_back( edgeID + 1);
}
};
for( int i = 0; i < _graph.PointsCount; ++i){
if( _graph.FirstEdge[ i] != -1){
Dfs( Dfs, i); break;
}
}
std::reverse( ANS.begin(), ANS.end());
例题
@LINK: https://editor.youkuaiyun.com/md/?not_checkout=1&articleId=130304774
;
证明给定图是欧拉回路图;
欧拉回路(无向图)
定义
#欧拉回路#
给定无向图G, 如果存在一个环x->...->x
满足G
中所有的边 都存在于这个环中一次, 那么这个环 称之为欧拉回路;
.
比如G: a-b-c-a
, 那么a-b-c-a (或b-c-a-b 或c-a-b-c)
是一个欧拉回路;
#欧拉回路图#
存在欧拉回路的图, 称之为欧拉回路图;
.
结论: 无向图G, 如果{每个点的度数都是偶数 | 所有边是连通的}, 那么G是欧拉回路图;
算法
求欧拉回路路径
和有向图求欧拉回路差不多, 只不过 由于是无向边(即a-b
边 在代码层面 是由a<->b
两条边组成的), 因此 当我们遍历了a->b
(她要放到答案里) 那么同时要把她对应的b->a
给Vis=1
掉;
std::vector< bool> Vis( _graph.EdgesCount << 1, 0);
auto Dfs = [&]( auto & _dfs, int _cur)->void{
for( ;_graph.FirstEdge[ _cur] != -1; ){
auto edgeID = _graph.FirstEdge[ _cur];
auto nex = _graph.DirectedEdges.at( edgeID).EndPoint;
_graph.FirstEdge[ _cur] = _graph.NextEdge[ edgeID];
if( Vis[edgeID] == 0){
Vis[edgeID] = Vis[edgeID^1] = 1;
_dfs( _dfs, nex);
ANS.push_back( edgeID);
}
}
};
for( int i = 0; i < _graph.PointsCount; ++i){
if( _graph.FirstEdge[ i] != -1){
Dfs( Dfs, i); break;
}
}
std::reverse( ANS.begin(), ANS.end());
术语
有向图
Given a Directed-Graph G = ( V , E ) G =(V, E) G=(V,E)
An Semi-Eulerian-Path (半欧拉路径) is a path (i.e., a sequence of edges satisfying any two consecutive-edges share a same point) such that the start-point and end-point of the path are distinct, and every edge e ∈ E e \in E e∈E occurs in the path exactly once;
+
The path would be the form s → . . . → t s ≠ t s \to ... \to t \ \ s\neq t s→...→t s=t, from the start-point s s s, you can traverse the graph with passing though every edge exactly once, and finally arrived at t t t.
+
The edges set of a Semi-Eulerian-Path equals to E E E;
+
The path focuses on the edges, not points (i.e., it would not pass though a Isolated-Point which has no adjacent-edges; a point maybe passed multiple times);
G G G is called Semi-Eulerian (半欧拉图) if it has an Semi-Eulerian-Path;
--
An Eulerian-Circuit (欧拉回路) is an Semi-Eulerian-Path in which the restriction s ≠ t s \neq t s=t replaced by s = t s = t s=t.
+
The path would be the form s → . . . → s s \to ... \to s s→...→s, from the start-point s s s, you can traverse the graph with passing though every edge exactly once, and finally arrived at s s s.
G G G is called Eulerian (欧拉图) if it has an Eulerian-Circuit;
--
An Eulerian-Path (欧拉路径) is either an Semi-Eulerian-Path or an Eulerian-Circuit.
无向图
Given a Undirected-Graph G = ( V , E ) G =(V, E) G=(V,E)
An Semi-Eulerian-Path (半欧拉路径) is a path (i.e., a sequence of edges satisfying any two consecutive-edges share a same point;) such that the start-point and end-point of the path are distinct, and every edge e ∈ E e \in E e∈E occurs in the path exactly once;
+
The path would be the form s − . . . − t s ≠ t s - ... - t \ \ s\neq t s−...−t s=t, from the start-point s s s, you can traverse the graph with passing though every edge exactly once, and finally arrived at t t t.
.
Note that an edge in a Undirected-Path, in fact it is Directed; e.g., a − b a-b a−b in the path denotes from a a a to b b b; although an Undirected-Edge a − b a-b a−b has two possible directions ( a → b a\to b a→b or b → a b\to a b→a), but the direction of any edge a − b a-b a−b is unique in a path.
+
The edges set of a Semi-Eulerian-Path equals to E E E;
+
The path focuses on the edges, not points (i.e., it would not pass though a Isolated-Point which has no adjacent-edges; a point maybe passed multiple times);
G G