定理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 #includeview code#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;
}
尤拉迴路的判定和求解
2 有向圖 尤拉迴路的求解 無向圖 連通 不考慮度為 0 的點 每個頂點度數都為偶數。ac include include include include include include include include include using namespace std const int ma...
尤拉迴路的判定 poj 1300
這個題卡了一上午卡到心態 卡到欲仙欲死。各種bug蜜汁出現。一邊一遍的除錯,忽然發現思考成熟是多麼的重要!最後是乙個短路效應的問題,懷疑人生!這個題就是統計出度和入度,就是建圖有點麻煩,其實也不算太麻煩了。對於無向圖而言就是 判斷是否滿足沒有奇度頂點,或者奇度定點只有兩個,並且這兩個奇度頂點其中乙個...
判定表與判定樹的畫法 判定樹和判定表
判定樹又稱決策樹,是一種描述加工的圖形工具,適合描述問題處理中具有多個判斷,而且每個決策與若干條件有關。使用判定樹進行描述時,應該從問題的文字描述中分清哪些是判定條件,哪些是判定的決策,根據描述材料中的聯結詞找出判定條件的從屬關係 並列關係 選擇關係,根據它們構造判定樹。例4.5 某工廠對工人的超產...