歐拉回路的基本概念

歐拉回路相關定義:

|| 如果圖G(有向圖或者無向圖)中有一條通路,該通路上所有邊一次且僅有一次行遍所有頂點,那麼這條通路稱爲歐拉通路

|| 如果圖G中所有邊一次且僅有一次行遍所有頂點,稱圖G有歐拉回路

|| 具有歐拉回路的圖稱爲歐拉圖,不具有歐拉回路但具有歐拉通路的圖稱爲半歐拉圖


歐拉回路的定理和推論:

|| 無向圖G存在歐拉通路的充要條件爲: G爲連通圖,且G有0或2個奇度節點( 度數爲奇度的節點)

|| 推論1:當無向圖G只有兩個奇度節點時,那麼其中的歐拉通路以這兩個節點爲端點

|| 推論2:當無向圖G沒有奇度節點時,那麼G必有歐拉回路

|| 推論3:無向圖G爲歐拉圖的充要條件是:G爲連通圖,且G有0個奇度節點

|| 有向圖G存在歐拉通路的充要條件爲:(爲了好記憶把出度入度不相等的點命名爲“異點”)
D爲有向圖,D的基圖連通,並且所有頂點的出度與入度都相等;或者除兩個頂點外,其餘頂點的出度與入度都相等,而這兩個頂點中一個頂點的出度與入度之差爲1,另一個頂點的出度與入度之差爲-1。

|| 簡化:D爲連通有向圖,且有0個或者2個異點(且這兩兩個異點的出入度差分別爲±1)

|| 推論1: 當D除出、入度之差爲1,-1的兩個頂點之外,其餘頂點的出度與入度都相等時,D的有向歐拉通路必以出、入度之差爲1的頂點作爲始點,以出、入度之差爲-1的頂點作爲終點。

|| 推論2: 當D的所有頂點的出、入度都相等時,D中存在有向歐拉回路。

|| 推論3: 有向圖D爲有向歐拉圖的充分必要條件是D的基圖爲連通圖,並且所有頂點的出、入度都相等。


歐拉回路的求解

|| DFS搜索求解歐拉回路:
基本思路:利用歐拉定理判斷出一個圖存在歐拉回路或歐拉通路後,選擇一個正確的起始頂點,用DFS算法遍歷所有的邊(每一條邊只遍歷一次),遇到走不通就回退。在搜索前進方向上將遍歷過的邊按順序記錄下來。這組邊的排列就組成了一條歐拉通路或迴路。

#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int ans[200];
int top;
int N,M;
int mp[200][200];
void dfs(int x)
{
    int i;
    top++;
    ans[top]=x;
    for (i=1; i<=N; i++)
    {
        if(mp[x][i]>0)
        {
            mp[x][i]=mp[i][x]=0;///刪除此邊
            dfs(i);
            break;
        }
    }
}

void fleury(int x)
{
    int brige,i;
    top=1;
    ans[top]=x;///將起點放入Euler路徑中
    while(top>=0)
    {
        brige=0;
        for (i=1; i<=N; i++) /// 試圖搜索一條邊不是割邊(橋)
        {
            if(mp[ans[top]][i]>0)///存在一條可以擴展的邊
            {
                brige=1;
                break;
            }
        }
        if (!brige)/// 如果沒有點可以擴展,輸出並出棧
        {
            printf("%d ", ans[top]);
            top--;
        }
        else     /// 否則繼續搜索歐拉路徑
        {
            top--;///爲了回溯
            dfs(ans[top+1]);
        }
    }
}

int main()
{
    int x,y,deg,num,start,i,j;
    scanf("%d%d",&N,&M);
    memset(mp,0,sizeof (mp));
    for(i=1;i<=M; i++)
    {
        scanf("%d%d",&x,&y);
        mp[x][y]=1;
        mp[y][x]=1;
    }
    num=0;
    start=1;///這裏初始化爲1
    for(i=1; i<=N; i++)
    {
        deg=0;
        for(j=1; j<=N; j++)
        {
            deg+=mp[i][j];
        }
        if(deg%2==1)///奇度頂點
        {
            start=i;
            num++;
        }
    }
    if(num==0||num==2)
    {
        fleury(start);
    }
    else
    {
        puts("No Euler path");
    }
    return 0;
}

|| Fleury(佛羅萊)算法:(算法的關鍵是:能不走橋就不去走橋,實在無路可走了纔去走橋)
在這裏插入圖片描述

#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int ans[200];
int top;
int N,M;
int mp[200][200];
void dfs(int x)
{
    int i;
    top++;
    ans[top]=x;
    for (i=1; i<=N; i++)
    {
        if(mp[x][i]>0)
        {
            mp[x][i]=mp[i][x]=0;///刪除此邊
            dfs(i);
            break;
        }
    }
}

void fleury(int x)
{
    int brige,i;
    top=1;
    ans[top]=x;///將起點放入Euler路徑中
    while(top>=0)
    {
        brige=0;
        for (i=1; i<=N; i++) /// 試圖搜索一條邊不是割邊(橋)
        {
            if(mp[ans[top]][i]>0)///存在一條可以擴展的邊
            {
                brige=1;
                break;
            }
        }
        if (!brige)/// 如果沒有點可以擴展,輸出並出棧
        {
            printf("%d ", ans[top]);
            top--;
        }
        else     /// 否則繼續搜索歐拉路徑
        {
            top--;///爲了回溯
            dfs(ans[top+1]);
        }
    }
}

int main()
{
    int x,y,deg,num,start,i,j;
    scanf("%d%d",&N,&M);
    memset(mp,0,sizeof (mp));
    for(i=1;i<=M; i++)
    {
        scanf("%d%d",&x,&y);
        mp[x][y]=1;
        mp[y][x]=1;
    }
    num=0;
    start=1;///這裏初始化爲1
    for(i=1; i<=N; i++)
    {
        deg=0;
        for(j=1; j<=N; j++)
        {
            deg+=mp[i][j];
        }
        if(deg%2==1)///奇度頂點
        {
            start=i;
            num++;
        }
    }
    if(num==0||num==2)
    {
        fleury(start);
    }
    else
    {
        puts("No Euler path");
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章