看了別人的代碼直接看不懂,加了printf才明白
他的博客鏈接:https://www.cnblogs.com/crackpotisback/p/3964249.html
定理:若圖G中含有Euler通路,則稱圖G爲半歐拉圖。若一個圖是歐拉圖或者是半歐拉圖,則稱該圖是可以遍歷的。
如果所有的頂點的度都爲偶數,那麼就可以隨便指定一個點做歐拉環遊
如果頂點的度爲奇數的個數爲2,那麼歐拉通路的起點或者頂點應該爲這兩個頂點。
從V1開始,第一次的dfs爲 v1->v2->v3->v4>v2->v6->v1,並將這些頂點依次入棧,並且每次刪掉邊,出棧的時候判斷下該頂點還有沒有其它路徑,如果有的話,就要以它爲頂點再找個閉跡,然後把閉跡上的點依次入棧。
v6出棧時,發現e6,e10還沒被刪掉,對它進行一次dfs,每次dfs就是在剩下的邊找一條閉跡 v6->v4->v5->v6,並把這些頂點一次入棧。
出棧的頂點就構成了一條歐拉跡。
/*
六個頂點10條邊
6 10
1 1
1 2
1 6
2 3
2 4
2 6
3 4
4 5
4 6
5 6
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <climits>
#include <vector>
#include <queue>
#include <cstdlib>
#include <string>
#include <set>
#include <stack>
#define LL long long
#define pii pair<int,int>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1000;
bool e[maxn][maxn];
int n,m;
stack<int>stk;
void dfs(int u){
stk.push(u);
cout<<u<<"入棧"<<endl;
for(int i = 1; i <= n; i++){
if(e[u][i]){
e[u][i] = false;
e[i][u] = false;
cout<<u<<" "<<i<<"的邊刪除掉"<<endl;
cout<<"dfs "<<i<<endl;
dfs(i);
cout<<"dfs "<<i<<" 結束"<<endl;
break;
}
}
}
void Fleury(int x){
while(!stk.empty()) stk.pop();
stk.push(x);
cout<<x<<"起點入棧"<<endl;
int i;
while(!stk.empty()){
int u = stk.top();
stk.pop();
cout<<u<<"出棧"<<endl;
for(i = 1; i <= n; i++)
if(e[u][i]) break;
if(i <= n)
{
cout<<"找到邊"<<u<<",並dfs它 "<<u<<endl;
dfs(u);
}
else
{
printf("歐拉路徑:%d \n",u);
}
cout<<"一次循環結束"<<endl;
}
puts("");
}
int main() {
int u,v,cnt,degree,st;
while(~scanf("%d %d",&n,&m)){
memset(e,false,sizeof(e));
for(int i = 0; i < m; i++){
scanf("%d %d",&u,&v);
e[u][v] = e[v][u] = true;
}
cnt = 0;
st = 1;
for(int i = 1; i <= n; i++){
for(int j = 1,degree = 0; j <= n; j++)
{
if(e[i][j]) degree++;
}
if(degree&1)
{
st = i;
cnt++;
}
}
if(cnt == 2 || !cnt) Fleury(st);
else puts("No Euler path");
}
return 0;
}