欧拉路径、欧拉回路、欧拉图傻傻分不清楚?看这一篇就够了!

推荐在 cnblogs 阅读

欧拉路径、回路、图

前言

当一手标题党,快乐~

之前一直分不清楚,写篇笔记分辨一下。

欧拉路径

可以一笔画的路径,称为欧拉路径。不要求起点终点为同一点。

判定:

  • 有向图:图中只有一个出度比入度大 1 1 1 的点(起点),与一个入度比出度大 1 1 1 的点(终点),其余点出入度相等。
  • 无向图:图中只有两个奇点(起点和终点),其余点都是偶点。

当然,将有向边视作无向边后,路径必须连通。

欧拉回路

在欧拉路径的基础上,起点终点是同一点。

判定:

  • 有向图:所有点的出入度相等。
  • 无向图:所有点都是偶点。

欧拉图

  • 欧拉图:具有欧拉回路的图。
  • 半欧拉图:存在欧拉路径、但没有欧拉回路的图。

判断方法

判断一个图是否有欧拉路或欧拉回路,要用到 Fleury 算法。(虽然这不是文章的重点,重点是上文)

用 DFS 实现。

算法核心:除非都是桥,否则走桥边。

P7771 【模板】欧拉路径

code

#include<bits/stdc++.h>
using namespace std;

#define int long long

const int MAXN=1e5+5;

int n,m;
int tmp[MAXN];
int rd[MAXN],cd[MAXN];
stack<int> st;
vector<int> G[MAXN];

void dfs(int S)
{
    for(int i=tmp[S];i<G[S].size();i=tmp[S])
        tmp[S]=i+1,dfs(G[S][i]);
    // tmp[S] : G[S][1,2,...,tmp[S]-1] 都已访问,下一次从 G[S][tmp[S]] 开始
    st.push(S);
}

signed main()
{
    scanf("%lld%lld",&n,&m);
    for(int i=1,u,v;i<=m;i++)
    {
        scanf("%lld%lld",&u,&v);
        G[u].push_back(v); // 注意有向图
        cd[u]++,rd[v]++;
    }
    for(int i=1;i<=n;i++) sort(G[i].begin(),G[i].end());
    int S=1,c1=0,c2=0;
    bool flg=1; // 是否所有点出入度相等
    for(int i=1;i<=n;i++)
    {
        if(cd[i]!=rd[i])
        {
            flg=0;
            if(cd[i]-rd[i]==1) c1++,S=i; // 出度比入度大 1
            else if(rd[i]-cd[i]==1) c2++;
            else return puts("No"),0;
        }
    }
    if(flg==0&&!(c1==c2&&c1==1))
        return puts("No"),0; // 不满足判定条件
    dfs(S);
    while(!st.empty())
        printf("%lld ",st.top()),st.pop();
    return 0;
}
  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于无向图,欧拉回路的判定条件是所有顶点的度数都为偶数,因此可以通过统计每个顶点的度数来判断是否存在欧拉回路。对于有向图,欧拉回路的判定条件是每个顶点的入度等于出度,因此需要统计每个顶点的入度和出度。以下是用C语言实现的无向图和有向图欧拉回路的判定代码: ```c #include <stdio.h> #define MAXN 1000 int G[MAXN][MAXN]; // 邻接矩阵表示图 int degree[MAXN]; // 存储每个顶点的度数(无向图)或入度减出度(有向图) int isEulerian(int n, int isDirected) { int i, j, odd = 0; for (i = 0; i < n; i++) { degree[i] = 0; for (j = 0; j < n; j++) { if (G[i][j]) { degree[i]++; } } if (degree[i] % 2 == 1) { odd++; } } if (isDirected) { for (i = 0; i < n; i++) { degree[i] = 0; for (j = 0; j < n; j++) { if (G[i][j]) { degree[i]++; degree[j]--; } } if (degree[i] != 0) { return 0; } } } return (odd == 0); } int main() { int n, m, i, j, a, b, isDirected; scanf("%d%d%d", &n, &m, &isDirected); for (i = 0; i < m; i++) { scanf("%d%d", &a, &b); G[a][b] = G[b][a] = 1; // 无向图边的两个方向都要标记 if (isDirected) { G[a][b] = 1; // 有向图只需要标记一次 } } if (isEulerian(n, isDirected)) { printf("Exist Eulerian circuit\n"); } else { printf("Not exist Eulerian circuit\n"); } return 0; } ``` 其中,`G` 是一个大小为 `n` 的邻接矩阵,如果 `G[i][j]` 为 `1`,则表示存在从顶点 `i` 到顶点 `j` 的边。`degree` 数组用于存储每个顶点的度数或入度减出度。`isEulerian` 函数判断是否存在欧拉回路,其中 `n` 表示顶点数,`isDirected` 表示是否为有向图,返回值为 `1` 则表示存在欧拉回路,否则不存在。在 `main` 函数中,首先读入图的信息,然后调用 `isEulerian` 函数判断是否存在欧拉回路,并输出结果。 需要注意的是,对于无向图,如果存在欧拉回路,则可以随便从一个顶点出发,遍历整个图;对于有向图,则需要从一个入度等于出度的顶点出发,遍历整个图。因此,如果存在欧拉回路,还需要找到一个起点,并输出遍历路径

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值