欧拉回路与欧拉路径

欧拉回路是从某点出发不重复经过每条边后回到起点的路径,欧拉路径则不需要回到起点。无向图欧拉回路的条件是连通且所有顶点度为偶数,欧拉路径则是连通且仅两个顶点度为奇数。有向图欧拉回路要求基图联通且所有顶点入度等于出度,欧拉路径需一个顶点入度小于出度1,另一个顶点反之。非欧拉图可通过加边转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义

  欧拉回路:从图上一个点u出发不重复地经过每一条边后,再次回到点u的一条路径。

  欧拉路径:从图上一个点u出发不重复地经过每一条边的一条路径(不必回到点u)。

  欧拉图即存在欧拉回路的图,半欧拉图即存在欧拉路径的图。

  而要求每个点只走一次的模型是哈密顿环。

定理

  (1)无向图欧拉回路的判定:图G为连通图,所有顶点的度为偶数。

  (2)无向图欧拉路径的判定:图G为连通图,除有2个顶点度为奇数外,其他顶点度都为偶数。

  (3)有向图欧拉回路的判定:图G的基图联通(忽略有向图所有边的方向),所有顶点的入度等于出度。

  (4)有向图欧拉路径的判定:图G的基图联通,存在顶点u的入度比出度小1,v入度比出度大一,其余所有顶点的入度等于出度。(此时u即路径的起点,v即终点)

其他定理

  (5)无向图为(半)欧拉图时,只需用1笔画成;无向图为非(半)欧拉图时,即奇点(度为奇数的点)数k>2,需用k/2笔画成。

  (6)可以用加边的方式把一个非欧拉图变成欧拉图。对于无向图来说,每个奇点都需加一个度,加的边为 奇点数/2 ;对于有向图来说,每个点都需加上入度与出度之差,加的边数为每个点入度与出度之差的绝对值之和再除以2。

  一个图的奇点数一定是偶数。

求欧拉回路欧拉路径

在无向图中实现

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;
 
int G[100][100], n, du[100], ans[10000], temp, len;
 
void dfs(int k)
{
    for(int i = 1; i <= 100; i++){
        if(G[k][i]){
            G[k][i] = 0;
            G[i][k] = 0;
            dfs(i);
        }
    }
    ans[len++] = k;  //保存路径
}
 
int main()
{
    cin>>n;
    for(int i = 1; i <= n; i++){
        int x, y;
        scanf("%d %d", &x, &y);
        du[x]++;  //x的度数++
        du[y]++;
        G[x][y] = 1;  //建图
        G[y][x] = 1;
    }
    for(int i = 1; i <= 100; i++){
        if(du[i] % 2 == 1) //如果说度数为奇数
            temp++;
    }
    if(temp != 0 && temp != 2) printf("既不是欧拉回路也不是欧拉路径\n");
    if(temp == 0){ //是欧拉回路,所有的度数都为偶数
        for(int i = 1; i <= 100; i++){
            if(du[i] != 0){  //随便找到一个点
                dfs(i);
                break;
            }
        }
    }
    if(temp == 2){  //是欧拉路径, 因为正好就有两个度数为奇数的点
        for(int i = 1; i <= 100; i++){
            if(du[i] % 2 == 1){  //因为,欧拉路径的起点应该是度数为奇数的点,所以遍历找到一个度数为奇数的点
                dfs(i);
                break;
            }
        }
    }
    for(int i = len - 1; i >= 1; i--){
        printf("%d", ans[i]);
    }
    return 0;
}
 

在有向图中实现

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;
 
struct node
{
    int to;   //出度
    int from; //入度
}du[100];
 
int G[100][100], n, ans[10000], temp, len, a, b;
 
void dfs(int k)  //
{
    for(int i = 1; i <= 100; i++){
        if(G[k][i]){
            G[k][i] = 0;
            dfs(i);
        }
    }
    ans[len++] = k;  //保存路径
}
 
int main()
{
    cin>>n;
    for(int i = 1; i <= n; i++){
        int x, y;
        scanf("%d %d", &x, &y); //从x指向y
        du[x].to++;    //x的出度+1
        du[y].from++;  //y的入度+1
        G[x][y] = 1;   //建图,从x指向y
    }
    for(int i = 1; i <= 100; i++){
        if(du[i].to != du[i].from) temp++;        //入度数不等与出度数
        else if(du[i].to - du[i].from == 1) a++;  //出度比入度多1
        else if(du[i].from - du[i].to == 1) b++;  //入度比出度多1
 
    }
    if(temp != 0 && temp != 2) printf("既不是欧拉回路也不是欧拉路径\n");
    if(temp == 0){ //是欧拉回路,所有的入度都等于出度
        for(int i = 1; i <= 100; i++){
            if(du[i].to != 0){  //随便找到一个点
                dfs(i);
                break;
            }
        }
    }
    if(temp == 2 && a == 1 && b == 1){  //是欧拉路径, 因为仅 i 点的出度比入度多 1 , j 点的的入度比出度多 1 。
        for(int i = 1; i <= 100; i++){
            if(du[i].to - du[i].from == 1){  //因为,欧拉路径的起点应该是出度比入度多 1
                dfs(i);
                break;
            }
        }
    }
    for(int i = len - 1; i >= 1; i--){
        printf("%d", ans[i]);
    }
    return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值