• 欧拉路/欧拉回路


    欧拉路/欧拉回路简介

    经过图中所有边恰好一次的通路称为欧拉通路或欧拉路。

    经过图中所有边恰好一次的回路称为欧拉回路。

    判别法

    对于无向图G,G中存在欧拉回路当且仅当G中所有度非0的点是连通的且没有奇数度数的点。

    对于无向图G,G中存在欧拉路当且仅当G中所有非0的点是连通的且G中恰有0或2个奇数度数的点(0个表示存在欧拉回路)。

    对于有向图G,G中存在欧拉回路当且仅当G中所有度非0的点是强连通的且每个点的入度和出度相同。

    对于有向图G,G中存在欧拉路当且仅当:

    将G中所有有向边改为无向边后,G中所有度非0的点是连通的;

    最多只有一个点的出度减去入度为1;

    最多只有一个点的入度减去出度为1;

    其他所有点的入度等于出度。

    流程

    先判断图中是否存在欧拉图(检查非0的点的连通性及度数)

    然后采用dfs来构造求解欧拉路

    令P为最终的路径序列,记路径起点为x(如果无向图全为偶数度数的点则随便找一个度数非0的点为x,否则找2个奇数点中任意一个为x;如果有向图所有点入度等于出度则随便找一个为x,否则找出度减入度为1的点为x);

    dfs(node u):

    遍历所有u连出去的边u→v,且u→v之前没有被访问过;

    将边u→v打上标记(如果是无向图则v→u也要打上标记);

    dfs(v);

    将边u→v添加到路径序列P中;

    dfs(x)结束后,将P中记录的边倒序输出,即为求得的欧拉路、

    时间复杂度: O ( n + m ) O(n+m) O(n+m)(找起点 O ( n ) O(n) O(n),找欧拉路 O ( m ) O(m) O(m)

    有向图(有连通性保证)

    vector edge[N];
    int n, m, l, f[N], ind[N], outd[N], c[M];
    inline void dfs(int x)
    {
        while (f[x] < outd[x])
        {
            int y = edge[x][f[x]];
            f[x]++;
            dfs(y);
            c[++l] = y;
        }
    }
    inline void Euler()
    {
        int x = 0, y = 0, z = 0; // x:起点,y:出度比入度大1,z:出度不等于入度的点
        for (int i = 1; i <= n; i++)
        {
            if (ind[i] + 1 == outd[i])
                x = i, ++y;
            if (ind[i] != outd[i])
                ++z;
        }
        if (!((y == 1 && z == 2) || !z))
        {
            printf("No\n");
            return;
        }
        if (!x)
            for (int i = 1; i <= n; i++)
                if (ind[i])
                    x = i;
        memset(f, 0, sizeof f);
        l = 0;
        dfs(x);
        c[++l] = x;
        if (l == m + 1)
            printf("Yes\n");
        else
        {
            printf("No\n");
            return;
        }
        for (int i = l; i; --i)
            printf("%d ", c[i]);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    无向图(不保证连通性)

    struct Node
    {
        int y, idx;
        Node(int _y, int _idx)
        {
            y = _y;
            idx = _idx;
        }
    };
    vector edge[N];
    int n, m, l, cnt = 1, f[N], d[N], c[M];
    bool b[2 * M];
    inline void dfs(int x)
    {
        while (f[x] < d[x])
        {
            int y = edge[x][f[x]].y, idx = edge[x][f[x]].idx;
            if (!b[idx])
            {
                f[x]++;
                b[idx] = b[idx ^ 1] = true;
                dfs(y);
                c[++l] = y;
            }
            else
                f[x]++;
        }
    }
    inline void Euler()
    {
        int x = 0, y = 0;
        for (int i = 1; i <= n; i++)
            if (d[i] & 1)
                x = i, ++y;
        if (y && y != 2)
        {
            printf("No\n");
            return;
        }
        if (!x)
            for (int i = 1; i <= n; i++)
                if (d[i])
                    x = i;
        memset(f, 0, sizeof f);
        memset(b, false, sizeof b);
        l = 0;
        dfs(x);
        c[++l] = x;
        if (l != m + 1)
        {
            printf("No\n");
            return;
        }
        printf("Yes\n");
         for (int i = l; i; --i)
            printf("%d ", c[i]);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
  • 相关阅读:
    JavaScript入门到精通(五)连载
    SaaS 架构实现理论(二)多租户/高性能多租户
    为什么要学习C++
    LeetCode刷题系列之-多数之和类型
    在国内企业做数据治理,建议您考个DAMA-CDGA/CDGP证书
    公开可用的API 合集
    数据结构——时间复杂度与空间复杂度
    java参数传递
    ubuntu 20 安装搜狗输入法
    QT QFrame控件使用详解
  • 原文地址:https://blog.csdn.net/qq_61540355/article/details/126003801