算法 {欧拉回路}

算法 {

欧拉回路(有向图)

定义

#欧拉回路#
给定有向图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->aVis=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 eE 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 eE 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 ab in the path denotes from a a a to b b b; although an Undirected-Edge a − b a-b ab has two possible directions ( a → b a\to b ab or b → a b\to a ba), but the direction of any edge a − b a-b ab 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值