1. 程式人生 > >尤拉圖知識總結

尤拉圖知識總結

尤拉圖

尤拉圖通路(迴路):通過圖中所有邊一次且僅一次,並且過每一頂點的通路(迴路)無向圖判斷G有尤拉通路:G連通,且G中奇數度的點只有0或2個。G有尤拉迴路:G連通,且G中都是偶數度點(奇數度點為零)。有向圖判斷D有尤拉通路:D連通,除兩個頂點外(只有兩個),其餘頂點的入度等於出度。這兩個頂點一個出度比入度大1,一定是起點;另一個入度比出度大1,一定是終點(只能大1,且總共兩個這樣的點)。D有歐拉回路:D連通,D中所有點的入度等於出度。尤拉圖典型的問題有單詞拼接,一筆畫問題,其解題步驟大概相同第一步:根據有向圖或無向圖的條件,判斷是否具有尤拉通路(迴路);第二步:在判斷是否連通(dfs或並查集)一般判斷連通:遍歷節點次數是否等於節點總數。如果是通路:一定要從起點開始遍歷。
dfs方法:
//利用了單詞拼接的dfs模板 
int dfs(int k,int cnt){//深搜構造尤拉通路 k起點,cnt遍歷次數 
	if(cnt==m) return 1;//連通 
	for(int i=0;i<m;i++){
		if(k!=s[i].s||vis[i]) continue;
		vis[i]=1;
		jie[cnt]=i;//記錄路徑 
		if(dfs(s[i].e,cnt+1)) return 1;
		vis[i]=0;//回溯 
	}
	return 0;//不連通 
}

還有一種:
void euler (int k){
	for(int i=0;i<m;i++){
		if(k==s[i].s&&!vis[i]){//找符合條件的單詞 (k==s[i].s意思:挑選符合的入度節點) 
			vis[i]=1;
			euler(s[i].e);//以這個單詞的結尾找下一個的開頭   euler(出度指向的節點) 
			q.push(s[i]);//遞迴從下自上,終點進棧保證順序輸出,如果是printf則是倒序 
		}//printf寫在這也是倒序 
	}
} 
上面這個函式不用回溯,因為是一找到底,再也找不到連通的下一個節點時,這個點必是終點,標記進棧,for迴圈再找,又有再也找不到連通的下一個節點時,這是聯通的倒數第二個節點,進棧,再找.........,直到for執行完。這是構造了一條路,是否聯通只需要判斷棧中元素是否為n(節點總數),是則連通。

傳送門:單詞拼接       一筆畫問題