【DayDayUp】【算法_图_欧拉回路_之一_Fleury (弗罗莱) 算法】

【坚持不能偷懒】

通过图(无向图有向图)中所有边且每边仅通过一次通路称为欧拉通路,相应的回路称为欧拉回路。具有欧拉回路的图称为欧拉图(Euler Graph),具有欧拉通路而无欧拉回路的图称为半欧拉图

——百度百科

现在开始通俗地扯扯。

什么是欧拉图捏,就是

从【一个点】出发

把【每条边】刷【一】发 且 只刷【一】发

然后【回到这个点】


满足这样条件的路径,就是一条【欧拉回路】

记某图为G

首先,我们要跑出一条欧拉回路,要先判断G有没有欧拉回路

判断:G每个点的度数为偶数(非0)

——因为每次进去再出来,度数相当于-2,如果是奇数,一定玩完儿


怎么跑出欧拉图呢,

譬如我们跑了一会儿,现在站在点 V 上

V可以向那些边跑呢?

如果V跑过一条边之后,没跑过的边构成的图,分成了两大块,这是不是就玩完儿了?

所以,V能跑的边,跑完了,不能让图边两块

这样的边有一个图论术语——【桥】

【描述为】

1、随机选个点加入

2、While(有边可加)

找这个点附近的边,如果只有桥,则加入该桥,否则选一个非桥边

3、无边可加时,已经找到所求



然后求桥的方法可以用Tarjan,效率是O(M)


而Fleury算法就是每次跑一个非桥的边,跑完就是一个欧拉回路

因为有M个边,每次Tarjan是O(M),

裸写应该就是 O(M^2)的复杂度


But,实际写的时候,不需要这么写,一般是直接Dfs刷刷刷就刷掉了


描述:

1 找个随机点,入栈

2 While(栈中非空)

取出栈顶,如果周围没有边(没用过的),则dfs该点

否则,弹出之,并输出

3 输出即为所求

DFS——深度搜索一条路径并把点加入。

下代码引用自——http://www.cnblogs.com/Lyush/archive/2013/04/22/3036659.html

void dfs(int x) {
    stk[top++] = x;
    for (int i = 1; i <= N; ++i) {
        if (mp[x][i]) {
            mp[x][i] = mp[i][x] = 0; // 删除此边
            dfs(i);
            break;
        }    
    }
}
void fleury(int ss) {
    int brige;
    top = 0;
    stk[top++] = ss; // 将起点放入Euler路径中
    while (top > 0) {
        brige = 1;
        for (int i = 1; i <= N; ++i) { // 试图搜索一条边不是割边(桥) 
            if (mp[stk[top-1]][i]) {
                brige = 0;
                break;
            }
        }
        if (brige) { // 如果没有点可以扩展,输出并出栈
            printf("%d ", stk[--top]);
        } else { // 否则继续搜索欧拉路径
            dfs(stk[--top]);
        }
    }
}


如上图

DFS,并把点入栈

如果DFS 出现如下 1 - 4 - 2 - 5 - 3 - 2 - 1栈中 1425321

1 周围没边,弹出1,输出【1】栈中142532

2 周围没边,弹出2,输出【1,2】 栈中 14253

3 周围没边,弹出3,输出【1,2,3】栈中1425

5 周围还有7,dfs出 1425765

弹出5 6 7 5 2 4 1

所以输出结果为【1,2,3,5,6,7,5,2,4,1】


为啥子这样操作呢

我们注意到,当加入 5->3 这条路径的时候,5->3实际上是一个桥

因为要跑尽所有的边,桥也是要加入的

用栈操作,就是弹到 5 这个点的时候,会先把5下面的回路跑出来







你可能感兴趣的:(算法_图)