歐拉回路



基本概念及定理
1. 歐拉通路、歐拉回路、歐拉圖
無向圖:
1) 設G是連通無向圖,則稱經過G的每條邊一次並且僅一次的路徑為歐拉通路;
2) 如果歐拉通路是回路(起點和終點是同一個頂點),則稱此回路為歐拉回路(Euler circuit);
3) 具有歐拉回路的無向圖G稱為歐拉圖(Euler graph)。
有向圖:
1) 設D是有向圖,D的基圖連通,則稱經過D的每條邊一次並且僅一次的有向路徑為有向
歐拉通路;
2) 如果有向歐拉通路是有向回路,則稱此有向回路為有向歐拉回路(directed Euler circuit);
3) 具有有向歐拉回路的有向圖D稱為有向歐拉圖(directed Euler graph)。
請思考圖5.1中的無向圖及有向圖是否為歐拉圖或有向歐拉圖。


                     圖5.1 歐拉回路及有向歐拉回路

2. 定理及推論
歐拉通路和歐拉回路的判定是很簡單的,請看下面的定理及推論。
定理5.1 無向圖G存在歐拉通路的充要條件是:
G為連通圖,並且G僅有兩個奇度結點(度數為奇數的頂點)或者無奇度結點。
推論5.1:
1) 當G是僅有兩個奇度結點的連通圖時,G的歐拉通路必以此兩個結點為端點。
2) 當G是無奇度結點的連通圖時,G必有歐拉回路。
3) G為歐拉圖(存在歐拉回路)的充分必要條件是G為無奇度結點的連通圖。


EXP圖5.1(a)所示的無向圖,存在兩個奇度頂點v2和v5,所以存在歐拉通路,且歐拉通路必
以這兩個頂點為起始頂點和終止頂點;該無向圖不存在歐拉回路。圖5.1(b)所示的無向圖為歐拉
圖。


定理5.2 有向圖D存在歐拉通路的充要條件是:
D為有向圖,D的基圖連通,並且所有頂點的出度與入度都相等;或者除兩個頂點外,其余
頂點的出度與入度都相等,而這兩個頂點中一個頂點的出度與入度之差為1,另一個頂點的出度
與入度之差為-1。
推論5.2:
1) 當D除出、入度之差為1,-1的兩個頂點之外,其余頂點的出度與入度都相等時,D的
有向歐拉通路必以出、入度之差為1的頂點作為始點,以出、入度之差為-1的頂點作為
終點。
2) 當D的所有頂點的出、入度都相等時,D中存在有向歐拉回路。
3) 有向圖D為有向歐拉圖的充分必要條件是D的基圖為連通圖,並且所有頂點的出、入度
都相等。
例如圖5.1(c)所示的有向圖,頂點v2和v4入度和出度均為1;頂點v1的出度為2、入度為1,
二者差值為1;頂 點v3的出度為1、入度為2,二者相差為-1;所以該有向圖只存在有向歐拉通路,
且必須以頂點v1為始點,以頂點v3為終點。圖5.1(d)所示的有向圖不存在有向歐拉通路。

 

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <iostream>
  4 using namespace std;
  5 const int MAX = 60;
  6 int edge[MAX][MAX];
  7 int degree[MAX];
  8 int in[MAX],out[MAX];
  9 int n,type;                           //judge  grape 類型
 10 int e;                                //邊數
 11 int top;                              // 棧底  初始化為 0;
 12 int stack[MAX];                       //記錄歐拉通路的路徑
 13 int vis[MAX];                         //是否已經訪問;
 14 void DFS(int cur)                     //連通性的判斷  是否完全訪問掉
 15 {
 16     int i ;
 17     for(i = 0; i<n; i++)
 18     {
 19         if(!vis[i]&&edge[cur][i])
 20         {
 21             vis[i] = 1;
 22             DFS(i);
 23         }
 24     }
 25 }
 26 
 27 
 28 // 判斷是否存在歐拉回路:
 29 // 無向圖中: 連通圖且所有頂點度數為偶數
 30 // 有向圖中: 連通圖且所有頂點的入度等於出度
 31 bool judge()
 32 {
 33     memset(vis,0,sizeof(vis));        //訪問初始化
 34     DFS(0);
 35     for(int i =0; i<n; i++)
 36     {
 37         if(!vis[i])
 38             return false;
 39     }                            //連通性的判斷  是否完全訪問掉
 40     if(type)                     //有向圖
 41     {
 42         for (int i=0; i<n; i++)
 43             if (in[i] != out[i])
 44             {
 45                 return false;
 46             }
 47     }
 48     else                           //無向圖
 49     {
 50         for(int i =0; i<n; i++)
 51         {
 52             if(degree[i]%2)
 53             {
 54                 return false;
 55             }
 56         }
 57     }
 58     return true;
 59 }
 60 // 有向圖的歐拉回路, 在 cur 點, 從 pos 點開始搜
 61 void DFS_first(int cur ,int pos)
 62 {
 63     int i,a,b;
 64     stack[top++] = cur;
 65     for(i = pos;i<n;i++)
 66     {
 67         if(edge[cur][i] != 0)
 68         {
 69             edge[cur][i] = 0;
 70             out[cur]--;
 71             in[i]--;
 72             DFS_first(i,0);
 73             break;
 74         }
 75     }
 76     if(i==n && top<n)  // 走投無路, 而且還有邊的時候, 退回一步
 77     {
 78         b = stack[--top];
 79         a = stack[--top];
 80         edge[a][b] = 1;
 81         out[a]++;
 82         in[b]++;
 83         DFS_first(a,b+1);
 84     }
 85 }
 86 // 無向圖的歐拉回路, cur 點, 從 pos 點開始搜
 87 void DFS_two(int cur,int pos)
 88 {
 89         int i,a,b;
 90     stack[top++] = cur;
 91     for(i = pos;i<n;i++)
 92     {
 93         if(edge[cur][i] != 0)
 94         {
 95              edge[i][cur] = 0;
 96             edge[cur][i] = 0;
 97 degree[cur]--;
 98 degree[i]--;
 99             DFS_two(i,0);
100             break;
101         }
102     }
103     if(i==n && top<n)  // 走投無路, 而且還有邊的時候, 退回一步
104     {
105         b = stack[--top];
106         a = stack[--top];
107         edge[a][b] = 1;
108         edge[b][a] = 1;
109         degree[a]++;
110         degree[b]++;
111         DFS_two(a,b+1);
112     }
113 
114 }
115 int main()
116 {
117     printf("0, 無向圖    1, 有向圖 : ");
118     scanf("%d", &type);
119     printf("輸入頂點個數: ");
120     scanf("%d",&n);
121     memset(edge,0,sizeof(edge));
122     memset(degree,0,sizeof(degree));  //無向圖的度數
123     memset(in,0,sizeof(in));          //有向圖的入度
124     memset(out,0,sizeof(out));        //有向圖的出度
125 
126     while(true)
127     {
128         int a,b;                      //邊集
129         scanf("%d %d",&a,&b);
130         if(!(a||b))                   //  0 0 break
131         {
132             break;
133         }
134         edge[a][b] = 1;
135         in[b]++;
136         out[a]++;
137         if(!type)                     // 如果是無向圖
138         {
139             edge[b][a] = 1;
140             degree[a]++;                   //無向圖的度數
141             degree[b]++;
142         }
143     }
144     if(judge())
145     {
146         printf("\n一條歐拉回路: ");
147         if(type)
148             DFS_first(0,0);
149         else
150             DFS_two(0,0);
151         for(int i =0; i<top; i++)
152         {
153             printf("%d",stack[i]);
154             if(i+1!=top)
155                 printf(" -> ");
156         }
157         putchar('\n');
158     }
159     else
160     {
161         printf("\n不存在歐拉回路!\n");
162     }
163     return 0;
164 }
View Code

摘自《圖論算法理論、實現及應用-王桂平》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM