中國郵遞員問題
一個郵遞員送信,要走完他負責投遞的所有街道(所有街道都是雙向通行的且每條街道能夠經過不止一次),完畢任務后回到郵局,應按如何的路線走,他所走的路程才會最短呢?
解決方式
1、圖論建模
因為街道是雙向通行的,我們能夠把它看成是賦權無向連通圖,將路口模型為點,街道模型為邊,街道的長度就是每條邊的權值,問題轉化為在圖中求一條回路,使得回路的總權值最小。
1.1最理想的情況
若圖中有歐拉回路,由於歐拉回路通過全部的邊,因此不論什么一個歐拉回路即為此問題的解。
1.2若G僅僅有兩個奇點Vi,Vj
則有從Vi到Vj的歐拉跡,從Vj回到Vi則必須反復一些邊,使反復邊的總長度最小,轉化為求從Vi到Vj的最短路徑。算法:
1) 找出奇點Vi,Vj之間的最短路徑P;
2) 令G’ = G + P;
3) G’為歐拉圖,G’的歐拉回路即為最優郵路。
1.3普通情況,奇點數大於2的時,郵路必須反復很多其它的邊。
Edmonds算法(匈牙利算法)
思想:
步驟:
1) 求出G全部奇點之間的最短路徑和距離;
2) 以G的全部奇點為結點(必為偶數),以他們之間的最短距離為節點之間邊的權值,得到一個全然圖G1;
3) 將M中的匹配邊(Vi,Vj)寫成Vi與Vj之間的最短路徑經過的全部邊集合Eij;
4) 令G’ = G U { Eij | (Vi,Vj)屬於M},則G’是歐拉圖,求出最優郵路。
2、詳細模塊實現
2.1最短路徑用 Dijkstra算法計算
Dijkstra算法是一種最短路徑算法,用於計算一個節點到其他全部節點的最短路徑。
2.1.1算法思想:
按路徑長度遞增次序產生最短路徑算法:
把V分成兩組:
1)S:已求出最短路徑的頂點的集合
2)V-S=T:尚未確定最短路徑的頂點集合
將T中頂點按最短路徑遞增的次序增加到S中,保證:
1)從源點V0到S中各頂點的最短路徑長度都不大於從V0到T中不論什么頂點的最短路徑長度
2)每一個頂點相應一個距離值
S中頂點:從V0到此頂點的最短路徑長度
T中頂點:從V0到此頂點的僅僅包含S中頂點作中間頂點的最短路徑長度
2.1.2求最短路徑步驟
1)初始時令 S={V0},T={ 其余頂點},T中頂點相應的距離值
若存在<V0,Vi>,d(V0,Vi)為<V0,Vi>弧上的權值;若不存在<V0,Vi>,d(V0,Vi)為∝
2)從T中選取一個其距離值為最小的頂點W且不在S中,增加S
3)對S中頂點的距離值進行改動:若加進W作中間頂點,從V0到Vi的距離值縮短,則改動此距離值;
反復上述步驟2、3,直到S中包括全部頂點,即W=Vi為止
2.2圖的連通性測試
檢測用戶輸入的圖是否是連通圖,不是的話沒辦法求解,提醒用戶又一次輸入。分兩種情況:
1)先查找圖中看是否有單點,假設存在,不連通,返回false;
2)對全部的頂點測試,假設存在頂點既不是單點,也不在連當前連通頂點集中,則表示存在多個連通分支,返回false;
2.3計算奇點個數,處理奇點,利用奇點之間的完美匹配來確定反復邊,使歐拉圖具有最優郵路
2.4用Fleury算法求最短歐拉回游
如果跡wi=v0e1v1…eivi已經選定,那么按下述方法從E-{e1,e2,…,ei}中選取邊ei+1:
1) ei+1與vi+1相關聯;
2)除非沒有別的邊可選擇,否則 ei+1不能是Gi=G-{e1,e2,…,ei}的割邊。
3)當(2)不能運行時,算法停止。
代碼沒有弄完,看這個:
http://www.cnblogs.com/guocai/archive/2012/07/08/2581979.html
