作一道Catenyms傷神無數,爲避免此狀況再次發生,在此將歐拉圖的斷定和求法加以總結php
注:本篇文章系菜鳥總結,大神們請自行忽略。
歐拉圖的斷定:html
1.首先,全部結點必須在同一個圖中。——-》採用並查集斷定算法
2.對於具備歐拉回路的圖:全部結點的入度和出度都相等,奇數度的結點個數爲0——–》統計斷定數組
3.對於具備歐拉通路的圖:圖中一個結點的入度比出度大1,一個結點的入度比出度小1,其他結點入度和出度相同。奇數度結點的個數爲2—–》統計斷定app
全部不知足以上條件的圖都不是歐拉圖。ide
歐拉圖的求法:wordpress
1.Fleury算法:(下面這段話來自離散課本)url
(1)任取v0∈V(G),令P0=v0. spa
(2)設Pi=v0e1v1e2…eivi已經行遍,按下面方法來從E(G)-{e1,e2,…,ei}中選取ei+1: code
(a)ei+1與vi相關聯;
(b)除非無別的邊可供行遍,不然ei+1不該該爲Gi=G-{e1,e2,…,ei}中的橋。
(3)當(2)不能再進行時,算法中止。
這個可能實現起來比較麻煩,由於還須要判斷邊是不是橋。
這個有興趣的話能夠去http://wenku.baidu.com/view/c32d8f49e45c3b3567ec8b40.html看看,要兩個財富點。。窮人下不起
2.套圈法:(下面這段話來自黑書)
歐拉回路:標記1爲待查找狀態古城Euler(i)尋找開始於定點i而且結束與i的歐拉回路,具體步驟以下:
(1)尋找從i出發的環P1P2…Px(P1=Px=i)
(2)標記頂點P1→x爲待查找狀態。
(3)對全部處於待查找狀態的結點Pj遞歸調用Euler(Pj)
將Pj找到的環Q1Q2…Qy插入到P1P2…Px中獲得歐拉回路P1P2…PjQ2…QyPj+1…Px
若是是求歐拉通路,預處理時找到度數爲奇數的兩個結點x和y以及一條從x到y的邊P1P2…Pk(x=P1;y=Pk),並初始化p[1]=k,p[i]=Pi(1<=i<=k)
這個算法的事件複雜度爲O(m)
僞代碼講解:
Euler(int i,int id)
{
若是點i還有出路未使用
{
找到該出路的目標結點j,該出路的邊的編號k
標記該出路已使用
Euler(j,k);
}
if (id!=-1) ans[top++]=該出路
}
以此圖說明:
首先找到A的出路1,而後到達結點C
找到C的惟一可用出路2,到達A
找到A中可用出路3,到達B
找到B的惟一可用出路4,回到A。
回溯時會依次將歐拉路4321存在ans數組裏,即獲得答案。
3.dfs法,來自YY
44 bool dfs(int st,int cnt)
45 {
46 int i;
47 if(cnt==n)
48 return 1;
49 for(i=0;i<n;i++)
50 {
51 if(edge[i].st<st||used[i])
52 continue;
53 else if(edge[i].st>st)
54 return false;
55 used[i]=true;
56 edge_order[cnt]=i;
57 if(dfs(edge[i].en,cnt+1))
58 return 1;
59 used[i]=false;//回溯判斷是否造成歐拉路徑
60 }
這個很好理解吧,就是深度搜索,直到找到歐拉回路爲止,算法複雜度比套圈什麼的要高一些。推薦套圈。