快乐暑假(八)——欧拉回路和哈密顿回路
歐拉回路
定義
歐拉回路:圖G中每條邊且只通過一次,并且經過每一頂點的回路
歐拉通路:(歐拉路徑):圖G中每條邊且只通過一次,并且經過每一頂點的通路
歐拉圖:存在歐拉回路的圖
半歐拉圖:存在歐拉通路的圖
極大連通子圖:在一個連通子圖中,包含和頂點有關所有的邊(the more the better),那就是極大連通子圖。
判定一個圖是否是(半)歐拉圖
無向圖:
定理1:無向圖G為歐拉圖,當且僅當G為連通圖且所有頂點的度為偶數。
推論1:無向圖G為半歐拉圖,當且僅當G為連通圖且除了兩個頂點的度為奇數外,所有頂點的度為偶數。
有向圖:
定理2:有向圖G{G}G為歐拉圖,當且僅當G{G}G的基圖為連通圖,且所有頂點的入度等于出度。
注:有向圖的基圖就是去掉所有方向的無向圖。
推論2:有向圖G{G}G為半歐拉圖,當且僅當G{G}G的基圖為連通圖,且存在頂點u{u}u的入度比出度大1,v{v}v的出度比入度大1,且其他的所有頂點的入度等于出度。
對于求解歐拉回路的,我們還需要以下兩個性質:
- 設C{C}C是歐拉圖G{G}G中的一個簡單的回路,將C{C}C中的邊從圖G{G}G中刪去的帶一個新的圖G1{G^{1}}G1,則G1{G^{1}}G1的每一個極大連通子圖都有一條歐拉回路。
證明: 若G{G}G為無向圖,則圖G′{G^{'}}G′的各頂點的度都為偶數;若G{G}G為有向圖,則圖G′{G^{'}}G′的各頂點的入度等于出度。
- 設C1{C_{1}}C1?、C2{C_{2}}C2?是圖G{G}G的兩個沒有公共邊,但至少有一個公共頂點的簡單回路,我們可以將他合并成一個新的簡單回路C′{C^{'}}C′。
證明: 按下圖合并
算法步驟
以無向圖為例:
-
在圖G{G}G中任意找到一個回路C{C}C;
-
將圖G{G}G中屬于回路C{C}C的邊刪除;
-
在殘余圖的各極大連通子圖中分別尋找歐拉回路;
-
將各極大連通子圖的歐拉回路合并到C{C}C中得到圖G{G}G的歐拉回路。
算法原理
代碼:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std;const int M = 100010,N = 1000010; int head[M],ver[N],Next[N],tot;//鄰接表 int stack[N],ans[N]; bool vis[N]; int n,m,top,t; void add(int x,int y) {ver[++tot] = y,Next[tot] = head[x],head[x] = tot; } void euler() {stack[++top] = 1;while(top > 0) {int x = stack[top], i =head[x];while(i && vis[i]) i = Next[i]; //找到一條未訪問的邊if(i) { //沿著這條邊模擬遞歸的過程,標記改變,并更新表頭stack[++top] = ver[i];head[x] = Next[i];vis[i] = vis[i^1] = true;} else { //與x相連的所有邊都已經訪問,模擬回溯過程,并記錄于答案棧中 top--;ans[++t] = x;}} } int main(){scanf("%d %d",&n,&m);tot = 1;for(int i = 1; i <= m; i++){int x,y;scanf("%d %d",&x,&y);add(x,y);add(y,x);}euler();for(int i = t; i ; i--) printf("%d\n",ans[i]);return 0; }參考:黃新軍,董永建《信息學奧賽一本通·提高篇》
哈密頓回路
總結
以上是生活随笔為你收集整理的快乐暑假(八)——欧拉回路和哈密顿回路的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: wallpaper怎么导入视频_vwal
- 下一篇: 测试自行车速度的软件,自行车速度测试