尤拉圖知識總結
阿新 • • 發佈:2019-02-11
尤拉圖
尤拉圖通路(迴路):通過圖中所有邊一次且僅一次,並且過每一頂點的通路(迴路)無向圖判斷G有尤拉通路:G連通,且G中奇數度的點只有0或2個。G有尤拉迴路:G連通,且G中都是偶數度點(奇數度點為零)。有向圖判斷D有尤拉通路:D連通,除兩個頂點外(只有兩個),其餘頂點的入度等於出度。這兩個頂點一個出度比入度大1,一定是起點;另一個入度比出度大1,一定是終點(只能大1,且總共兩個這樣的點)。D有歐拉回路:D連通,D中所有點的入度等於出度。尤拉圖典型的問題有單詞拼接,一筆畫問題,其解題步驟大概相同第一步:根據有向圖或無向圖的條件,判斷是否具有尤拉通路(迴路);第二步:在判斷是否連通(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;//不連通
}
還有一種:
上面這個函式不用回溯,因為是一找到底,再也找不到連通的下一個節點時,這個點必是終點,標記進棧,for迴圈再找,又有再也找不到連通的下一個節點時,這是聯通的倒數第二個節點,進棧,再找.........,直到for執行完。這是構造了一條路,是否聯通只需要判斷棧中元素是否為n(節點總數),是則連通。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寫在這也是倒序 } }
傳送門:單詞拼接 一筆畫問題