一筆畫問題
如果一個圖存在一筆畫,則一筆畫的路徑叫做歐拉路,如果最后又回到起點,那這個路徑叫做歐拉回路。
我們定義奇點是指跟這個點相連的邊數目有奇數個的點。對於能夠一筆畫的圖,我們有以下兩個定理。
定理1:存在歐拉路的條件:圖是連通的,有且只有2個奇點。
定理2:存在歐拉回路的條件:圖是連通的,有0個奇點。
兩個定理的正確性是顯而易見的,既然每條邊都要經過一次,那么對於歐拉路,除了起點和終點外,每個點如果進入了一次,顯然一定要出去一次,顯然是偶點。對於歐拉回路,每個點進入和出去次數一定都是相等的,顯然沒有奇點。
一筆畫性質:
■⒈凡是由偶點組成的連通圖,一定可以一筆畫成。畫時可以把任一偶點為起點,最后一定能以這個點為終點畫完此圖。
■⒉凡是只有兩個奇點的連通圖(其余都為偶點),一定可以一筆畫成。畫時必須把一個奇點為起點,另一個奇點為終點。
■⒊其他情況的圖都不能一筆畫出。(奇點數除以二便可算出此圖需幾筆畫成。)
求歐拉路的算法很簡單,使用深度優先遍歷即可。
根據一筆畫的兩個定理,如果尋找歐拉回路,對任意一個點執行深度優先遍歷;找歐拉路,則對一個奇點執行DFS,時間復雜度為O(m+n),m為邊數,n是點數。
l樣例輸入:第一行n,m,有n個點,m條邊,以下m行描述每條邊連接的兩點。
l 5 5
l 1 2
l 2 3
l 3 4
l 4 5
l 5 1
l樣例輸出:歐拉路或歐拉回路
l 1 5 4 3 2 1
歐拉路:
1 //歐拉路 2 3 #include<iostream> 4 #include<cstdio> 5 using namespace std; 6 int maps[1001][1001]; 7 int flag[1001]; 8 int tot,n,m; 9 int ans[1001],p=0; 10 void dfs(int num){ 11 for(int i=1;i<=m;i++) 12 if(maps[num][i]==1) 13 { 14 maps[num][i]=0; 15 maps[i][num]=0; 16 dfs(i); 17 ans[++p]=i; 18 } 19 } 20 int main() 21 { 22 int a,b,flag1=0,start=1; 23 scanf("%d%d",&m,&n); 24 for(int i=1;i<=n;i++) 25 { 26 scanf("%d%d",&a,&b); 27 maps[a][b]=1; 28 maps[b][a]=1; 29 flag[a]++; 30 flag[b]++; 31 } 32 for(int i=1;i<=n;i++) 33 { 34 if(flag[i]%2!=0) 35 { 36 if(flag1==0) 37 start=i; 38 flag1++; 39 } 40 if(flag1>2) 41 { 42 printf("Impossible"); 43 return 0; 44 } 45 } 46 dfs(start);//必須從奇點開始搜 47 for(int i=1;i<=p;i++) 48 printf("%d ",ans[i]); 49 return 0; 50 }
歐拉回路:
似乎比歐拉路還水:從1開始搜的;
1 //歐拉回路 2 3 #include<iostream> 4 #include<cstdio> 5 using namespace std; 6 int maps[1001][1001]; 7 int flag[1001]; 8 int n,m; 9 int ans[1001],p=0; 10 void dfs(int num){//搜哦搜 11 for(int i=1;i<=m;i++) 12 if(maps[num][i]==1) 13 { 14 maps[num][i]=0; 15 maps[i][num]=0; 16 dfs(i); 17 ans[++p]=i; 18 } 19 } 20 int main() 21 { 22 int a,b,flag1=0; 23 scanf("%d%d",&m,&n); 24 for(int i=1;i<=n;i++) 25 { 26 scanf("%d%d",&a,&b); 27 maps[a][b]=1; 28 maps[b][a]=1; 29 flag[a]++; 30 flag[b]++; 31 } 32 for(int i=1;i<=n;i++) 33 { 34 if(flag[i]%2!=0) 35 { 36 printf("Impossible"); 37 return 0; 38 } 39 } 40 dfs(1);//滿足的話從哪個點搜都可以; 41 for(int i=1;i<=p;i++) 42 printf("%d ",ans[i]); 43 printf("%d ",1); 44 return 0; 45 }