1. 程式人生 > >Fleury演算法 -求無向尤拉圖的歐拉回路

Fleury演算法 -求無向尤拉圖的歐拉回路

背景介紹

1) 尤拉圖:存在經過圖中每條邊恰好一次並且僅一次行遍所有點的迴路

  • 通俗來說,該回路有兩個特點:
    • 邊:包括圖中所有邊(不重複地)
    • 點:包括圖中所有點(可重複地)

2) 尤拉圖判斷:不存在奇度頂點

  • 通俗來說,圖中每個頂點與偶數條邊相連

3) 歐拉回路求解:判斷一個圖是尤拉圖,下一步就會問這條迴路具體是什麼,Fleury演算法就是用來找出無向尤拉圖可能的的歐拉回路

4) Fleury演算法

  1. 任意選擇圖中的一個頂點作為初始頂點a1
  2. 優先選擇走非橋(刪除該邊後不會連通分支不會增加,逼不得已再走橋。按照與該點連線邊數判斷:
    2.1 a1與某個點有兩條邊相連=>這兩條邊必為非橋
    2.2 a1與某個點僅一條邊相連:皆有可能(是否可能存在a1分別與a2、a3僅有一條邊,邊(a1,a2)為橋,而(a1,a3)非橋???)
  3. 若是未走完所有邊,繼續第二步

5)實現程式碼C++

#include<iostream>
using namespace std;
//該演算法適用於無向尤拉圖找出具體的尤拉通路 
int main()
{
	int n;
	cout<<"please input the order of metrix: ";
	cin>>n;
	
	int a[n+1][n+1];
	for(int i=1;i<=n;i++)//使用鄰接矩陣表示圖 
	{
		for(int j=1;j<=n;j++)
		{
			cin>>a[i][j];
		}
} int start=1,present=start,tmp=0; //演算法思想:能不走橋就不走橋 while(true) { int flag2=0,flag1=0; for(int j=1;j<=n;j++)//遍歷該點與其它所有點的鄰接關係 { if(a[present][j]>=2)//找到第一條非橋,就走它 { flag2++;//記錄是否存在非橋 a[present][j]--;//邊是二元關係,兩個點都要改變;包括了環的情況 a[j][present]--; cout<<"("<<
present<<","<<j<<")"<<" ";//模擬走的道路 present=j;//更新當前點 break;//找到就進入下一個點 } if(a[present][j]==1&&flag1==0)//記錄第一個與當前點存在一條邊(不一定是割邊)的點 { flag1++; tmp=j; } } if(flag2==0&&flag1==1)//只能走橋 { a[present][tmp]--; a[tmp][present]--; cout<<"("<<present<<","<<tmp<<")"<<" "; present=tmp; } if(flag2==0&&flag1==0)break;//當矩陣為零矩陣時結束 } return 0; }

6)測試用例

2(圖有兩個點,對應矩陣的階為2)
0 2
2 0

3
0 2 2
2 0 2
2 2 0

3
0 2 0
2 0 2
0 2 0

3
0 0 2
0 0 2
2 2 0

4 (第一個點有一個環)
2 0 1 1
0 0 1 1
1 1 0 0
1 1 0 0

收穫

  • 使用矩陣這個強大的工具表示圖,對圖的操作,如增刪邊,找回路等都可以有矩陣相應計算完成
  • 把思路理清楚後再用程式碼實現,程式設計時注意標記重置的位置