定理:
(一)一个图有欧拉回路当且仅当它是连通的且每个顶点都有偶数度。
(二)一个图有欧拉通路当且经当它是连通的且除两个顶点外,其他顶点都有偶数度。
在第二个定理下,含奇数度的两个节点中,一个必为欧拉通路起点,另一个必为欧拉通路的终点。
设G是一个无向的欧拉图,求G中的一条欧拉回路的算法为:
(1)任意选取G中的一个点V0,令P0 = V0。
(2)假设沿pi = v0e1v1e2v2......eivi走到了点vi,按照下面的方法从E - {e1,e2,...,ei}中选取ei + 1:
a)ei + 1与vi关联。
b)除非无别的边可以选择,否则ei + 1不应该是Gi = G - {e1,e2,...,ei}中的桥。
(3)当(2)不能再进行时算法停止。
可以证明的是,当算法停止时,所得到的简单回路pm = v0e1v1e2v2......emvm(vm == v0)为G中的一条欧拉回路。
#include <iostream> #include <cstdio> #include <fstream> #include <algorithm> #include <cmath> #include <deque> #include <vector> #include <list> #include <queue> #include <string> #include <cstring> #include <map> #define PI acos(-1.0) #define mem(a,b) memset(a,b,sizeof(a)) #define sca(a) scanf("%d",&a) #define pri(a) printf("%d\n",a) #define M 202 #define INF 100000001 using namespace std; typedef long long ll; struct stack { int top,node[M]; }s; int e[M][M],n; void dfs(int x) { int i; s.node[++s.top]=x; //cout<<s.top<<' '<<s.node[s.top]+1<<endl; for(i=0;i<n;i++) { if(e[i][x]>0) { e[i][x]=e[x][i]=0; //删除这条边 dfs(i); break; } } } void fleury(int x) { int i,flag; s.top=0; s.node[s.top]=x; while(s.top>=0) { flag=0; for(i=0;i<n;i++) { if(e[s.node[s.top]][i]>0) { flag=1; break; } } if(!flag) printf("%d ",s.node[s.top--]+1); else dfs(s.node[s.top--]); } puts(""); } int main( ) { int i,j,u,v,m,degree,num=0,start=0; scanf("%d%d",&n,&m); mem(e,0); for(i=0;i<m;i++) { scanf("%d%d",&u,&v); e[u-1][v-1]=e[v-1][u-1]=1; } for(i=0;i<n;i++) { degree=0; for(j=0;j<n;j++) degree+=e[i][j]; if(degree&1) { start=i; num++; } } if(num==0||num==2) fleury(start); else printf("No Euler path\n"); return 0; }
#include <iostream> #include <cstring> #include <vector> using namespace std; const int MAX = 10240; int N, M, pCnt[MAX]; int pMap[MAX][MAX]; vector<int> pVec; void Search(int x); void Euler_Circuit(); int main() { cin >> N >> M; memset(pMap, 0, sizeof(pMap)); for(int i = 1; i <= M; i++) { int s, e; cin >> s >> e; pMap[s][e] = pMap[e][s] = 1; // 无向图 } Euler_Circuit(); return 0; } void Euler_Circuit() { int nStart = 1, nOddNum = 0; // nStart保存起点,nOddNum保存有几个顶点有奇数度 memset(pCnt, 0, sizeof(pCnt)); for(int i = 1; i <= N; i++) { for(int j = 1; j <= N; j++) { pCnt[i] += pMap[i][j]; // 计算各个顶点的度 } } for(int i = 1; i <= N; i++) // 统计奇数度顶点的个数 { if(pCnt[i] & 1) { nStart = i; nOddNum++; } } if(nOddNum > 2 || nOddNum == 1) // 不存在欧拉回路 { cout << "Not Exsit Euler Circuit" << endl; } else { Search(nStart); for(int i = 0; i < pVec.size(); i++) { cout << pVec[i] << " "; } cout << endl; } } void Search(int x) { for(int i = 1; i <= N; i++) { if(pMap[x][i] == 1) { pMap[x][i] = pMap[i][x] = 0; // 删边 Search(i); } } pVec.push_back(x); }