Fleury演算法 -求無向尤拉圖的歐拉回路
阿新 • • 發佈:2019-02-13
背景介紹
1) 尤拉圖:存在經過圖中每條邊恰好一次並且僅一次行遍所有點的迴路
- 通俗來說,該回路有兩個特點:
- 邊:包括圖中所有邊(不重複地)
- 點:包括圖中所有點(可重複地)
2) 尤拉圖判斷:不存在奇度頂點
- 通俗來說,圖中每個頂點與偶數條邊相連
3) 歐拉回路求解:判斷一個圖是尤拉圖,下一步就會問這條迴路具體是什麼,Fleury演算法就是用來找出無向尤拉圖可能的的歐拉回路
4) Fleury演算法
- 任意選擇圖中的一個頂點作為初始頂點a1
- 優先選擇走非橋(刪除該邊後不會連通分支不會增加,逼不得已再走橋。按照與該點連線邊數判斷:
2.1 a1與某個點有兩條邊相連=>這兩條邊必為非橋
2.2 a1與某個點僅一條邊相連:皆有可能(是否可能存在a1分別與a2、a3僅有一條邊,邊(a1,a2)為橋,而(a1,a3)非橋???) - 若是未走完所有邊,繼續第二步
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
收穫
- 使用矩陣這個強大的工具表示圖,對圖的操作,如增刪邊,找回路等都可以有矩陣相應計算完成
- 把思路理清楚後再用程式碼實現,程式設計時注意標記重置的位置