有向圖的歐拉回路及尤拉道路
阿新 • • 發佈:2019-01-29
歐拉回路
//有向圖
//歐拉回路:1.圖連通2.每個點的入度等於出度//尤拉道路:1.圖連通2.每個點的入度等於出度或有兩個點入度不等於出度,且一個點出度比入度大一(起點),另一個點入度比出度小一(終點)如下圖只能從中間一點開始到中間另一點結束,並且起點出度比入度大一
//儲存路徑時需要注意一點,ans陣列是儲存的兩點,而不是一點是否被訪問過(這與圖的遍歷不同,我一開始就錯這),因為歐拉回路是可能重複經過某一點的
#include <cstdio> #include <iostream> #include <queue> using namespace std; int n; int a[101][101]; int indegree[101]; int outdegree[101]; int bfs(); int ans[101][101]; int compare(); void print(int i); int main() { int m,i,j,c,d; scanf("%d%d",&n,&m); for (i=1;i<=m;i++) { scanf("%d%d",&c,&d); a[c][d]=1; outdegree[c]++;//c的出度加一 indegree[d]++;//d的入度加一 } if (!bfs())//如果圖本身不連通 printf("No\n"); else if (compare())//如果入度等於出度 { printf("Yes\n"); printf("路徑為:\n"); print(1); } else printf("No\n"); return 0; } int bfs() { queue<int>q; int i; int vis[101],temp;//標記是否訪問過 for (i=1;i<=n;i++) vis[i]=0; q.push(1); vis[1]=1; while(!q.empty()) { temp=q.front(); q.pop(); for (i=1;i<=n;i++) if ((a[temp][i])&&(!vis[i])) { vis[i]=1; q.push(i); } } for (i=1;i<=n;i++) if (!vis[i]) { printf("%d\n",i); return 0; } return 1; } int compare() { int i; for (i=1;i<=n;i++) if (indegree[i]!=outdegree[i]) return 0; return 1; } void print(int i) { int v; for (v=1;v<=n;v++) if ((a[i][v])&&(!ans[i][v])) { ans[i][v]=1; printf("%d->%d\n",i,v); print(v); //遞迴搜尋路徑 } }
尤拉道路
//有向圖的尤拉道路的查詢即路徑列印方式與尤拉通路差不多,關鍵在於包含歐拉回路的情況下再考慮入度和出度相差1的情況
//有向圖的尤拉道路起點必須是出度比入度大一的那個點,所以要先掃描一遍找出那兩個點,如果都相等,那就參照歐拉回路的方式做,否則從該點開始路徑遞迴
#include <cstdio> #include <iostream> #include <queue> #include <cmath> using namespace std; int n; int a[101][101]; int indegree[101]; int outdegree[101]; int bfs(); int x[3]; int ans[101][101]; int compare(); void print(int i); int main() { int m,i,j,c,d; scanf("%d%d",&n,&m); x[1]=0; for (i=1;i<=m;i++) { scanf("%d%d",&c,&d); a[c][d]=1; outdegree[c]++;//c的出度加一 indegree[d]++;//d的入度加一 } if (!bfs())//如果圖本身不連通 printf("No\n"); else if (compare())//如果入度等於出度 { printf("Yes\n"); printf("路徑為:\n"); if (!x[1])//如果是歐拉回路,那麼哪一點開始都無所謂 print(1); else if (outdegree[x[1]]>outdegree[x[2]])//如果a[1]的出度大,那他就是起點 print(x[1]); else print(x[2]); } else printf("No\n"); return 0; } int bfs() { queue<int>q; int i; int vis[101],temp;//標記是否訪問過 for (i=1;i<=n;i++) vis[i]=0; q.push(1); vis[1]=1; while(!q.empty()) { temp=q.front(); q.pop(); for (i=1;i<=n;i++) if ((a[temp][i])&&(!vis[i])) { vis[i]=1; q.push(i); } } for (i=1;i<=n;i++) if (!vis[i]) { printf("%d\n",i); return 0; } return 1; } int compare() { int i,ok; ok=0; for (i=1;i<=n;i++) if (indegree[i]!=outdegree[i]) { ok++; if (ok>2)return 0;//如果入度出度不相等的節點數大於2,那肯定不是尤拉道路 else x[ok]=i; } if (!ok)//如果入度都等於出度,那麼是歐拉回路,自然是尤拉通路 return 1; if (fabs(indegree[x[1]]-indegree[x[2]])!=1)//如果入度相差不是1,那也不是歐拉回路 return 0; } void print(int i) { int v; for (v=1;v<=n;v++) if ((a[i][v])&&(!ans[i][v])) { ans[i][v]=1; printf("%d->%d\n",i,v); print(v); //遞迴搜尋路徑 } }