Hamilton迴路的判定與構造

2022-02-14 01:48:59 字數 2913 閱讀 8981

定理1:在乙個具有n個頂點的無向連通圖g中,如果任意兩個頂點的度數之和大於n,則g具有hamilton迴路。此條件為充分條件

定理2:設圖g = ,是hamilton圖,則對於v的任意乙個非空子集s,若以|s|表示s中元素數目,g-s表示g中刪除了s中的點以及與這些點關聯的邊後得到的子圖,則滿足g-s的連通分支數w(g-s)<=|s|。此條件為必要條件。

構造hamilton迴路的演算法過程,分成以下幾個步驟:

1. 任意找兩個相鄰的節點 s 和 t,在它們基礎上擴充套件出一條盡量長的沒有重複節點的路徑。也就是說,如果 s 與節點 v 相鄰,而且 v 不在路徑 s → t 上,則可以把該路徑變成 v → s → t,然後 v 成為新的 s。從 s 和 t 分別向兩頭擴充套件,直到無法擴為止,即所有與 s 或 t 相鄰的節點都在路徑 s → t 上。

2. 若 s 與 t 相鄰,則路徑 s → t 形成了乙個迴路。

3. 若 s 與 t 不相鄰,可以構造出乙個迴路。設路徑 s → t 上有 k + 2 個節點,依次為 s、 v1、 v2…… vk 和 t。可以證明存在節點 vi, i ∈ [1, k),滿足 vi 與 t 相鄰,且 vi+1 與 s 相鄰。證明方法也是根據鴿巢原理,既然與 s 和 t 相鄰的點都在該路徑上,它們分布的範圍只有 v1 ∼ vk 這 k 個點, k ≤ n - 2,而 d(s) + d(t) ≥ n,那麼可以想像,肯定存在乙個與 s 相鄰的點 vi 和乙個與 t 相鄰的點 vj, 滿足 j < i。那麼上面的命題也就顯然成立了。

找到了滿足條件的節點 vi 以後,就可以把原路徑變成 s → vi+1 → t → vi → s,即形成了乙個迴路。

4. 現在我們有了乙個沒有重複節點的迴路。如果它的長度為 n,則漢密爾頓迴路就找到了。

如果迴路的長度小於 n,由於整個圖是連通的,所以在該回路上,一定存在一點與迴路以外的點相鄰。那麼從該點處把迴路斷開,就變回了一條路徑。再按照步驟 1 的方法盡量擴充套件路徑,則一定有新的節點被加進來。接著回到步驟 2。

模板題:poj 2438 or hdu 4337 childrens dining

問題是求小朋友圍著桌子的座次就是求原圖中的乙個環,但是要求這個環不能包含所給出的每條邊,所以沒給出的邊卻是可以使用的,也就是說本題實際上是在原圖的反圖上求乙個環,即在每兩個可以坐在相鄰位置的小朋友連一條邊,否則不連。使得該環包含所有頂點,即hamilton迴路。

由於有2n個小朋友,且每個小朋友的敵人最多n-1個,所以,每個小朋友可以一起與座的小朋友最少有n+1個,即度數》=n+1,所以任意兩個小朋友度數之和d(u)+d(v)>=2n+2 > 2n,所以hamilton迴路存在。

**:

#include #include 

#include

#include

#include

using

namespace

std;

#define n 407

intvis[n],mp[n][n],ans[n];

intn,m;

void

init()

}memset(ans,

0,sizeof

(ans));

}void reverse(int ans[n],int s,int t) //

將ans陣列中s到t的部分倒置

}void

hamilton()

t = i; //

取任意連線s的點為t

vis[s] = vis[t] = 1

; ans[

0] =s;

ans[

1] =t;

while(1

)

}if(i >n)

break

; }

//將當前得到的序列倒置,s和t互換,從t繼續擴充套件,相當於在原來的序列上從s擴充套件

w = k - 1

; i = 0

; reverse(ans,i,w);

swap(s,t);

//從新的t向外擴充套件,相當於在原來的序列上從s向外擴充套件

while(1

)

}if(i >n)

break

; }

if(!mp[s][t]) //

如果s和t不相鄰,進行調整

//將從ans[i+1]到t部分的ans倒置

w = k - 1

; i++;

t =ans[i];

reverse(ans,i,w);

}//如果當前s和t相連

if(k == n) //

如果當前序列中包含n個元素,演算法結束

return

;

//當前序列中的元素個數小於n,尋找點ans[i],使得ans[i]與ans外一點相連

for(j=1;j<=n;j++)

s = ans[i-1

]; t =j;

reverse(ans,

0,i-1); //

將ans中s到ans[i-1]部分的ans倒置

reverse(ans,i,k-1); //

將ans中ans[i]到t的部分倒置

ans[k++] = j; //

將點j加入到ans的尾部

vis[j] = 1

; }

}int

main()

hamilton();

printf("%d

",ans[0

]);

for(i=1;i)

printf("%d

",ans[i]);

printf("\n

");}

return0;

}

view code

尤拉迴路的判定和求解

2 有向圖 尤拉迴路的求解 無向圖 連通 不考慮度為 0 的點 每個頂點度數都為偶數。ac include include include include include include include include include using namespace std const int ma...

尤拉迴路的判定 poj 1300

這個題卡了一上午卡到心態 卡到欲仙欲死。各種bug蜜汁出現。一邊一遍的除錯,忽然發現思考成熟是多麼的重要!最後是乙個短路效應的問題,懷疑人生!這個題就是統計出度和入度,就是建圖有點麻煩,其實也不算太麻煩了。對於無向圖而言就是 判斷是否滿足沒有奇度頂點,或者奇度定點只有兩個,並且這兩個奇度頂點其中乙個...

判定表與判定樹的畫法 判定樹和判定表

判定樹又稱決策樹,是一種描述加工的圖形工具,適合描述問題處理中具有多個判斷,而且每個決策與若干條件有關。使用判定樹進行描述時,應該從問題的文字描述中分清哪些是判定條件,哪些是判定的決策,根據描述材料中的聯結詞找出判定條件的從屬關係 並列關係 選擇關係,根據它們構造判定樹。例4.5 某工廠對工人的超產...