咕了好久的圖論的一小小小部分。
1、定義
歐拉路徑 :不重復經過圖上每一條邊的路徑
歐拉回路 : 起止點相同的歐拉路徑
2、判定
$\bullet$ 有向圖:
$\bullet$ 歐拉路徑 :圖中有且僅有 $1$ 個點出度比入度多 $1$ ,為起點;圖中有且僅有 $1$ 個點入度比出度多 $1$ ,為終點;其余節點 入度 $=$ 出度。
$\bullet$ 歐拉回路 :圖中所有點 入度 $=$ 出度,起止點為任意點。
$\bullet$ 無向圖:
$\bullet$ 歐拉路徑 :圖中僅有 $2$ 個點度數為奇數,其余點度數為偶數,這兩個奇數點可以任意選為起點終點。
$\bullet$ 歐拉回路 :所有點度數都是偶數,起止點任意。
其實這些概念還是很好理解的,有進就有出,否則肯定有走不通的,回路就是起止點連在一起了。
3、尋找
假設我們已經選好起點,那么一次對圖的 dfs 即可求出,我們只需要用棧記錄即可。
注意!如果題中要求按字典序,那最好是用 vector 或者鄰接矩陣。
附上例題:傳送門~。
哦對了,無向圖的最好是只用鄰接矩陣,不然刪邊很麻煩的!!
例題代碼,算是有向圖歐拉路徑的板子,一個通了別的也通了。
#include<cstdio> #include<queue> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<cctype> #include<vector> #include<string> #include<climits> #include<stack> using namespace std; template <typename T> inline void read(T &x){ x=0;char ch=getchar();bool f=0; while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();} while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); if(f)x=-x; } template <typename T,typename ...Args> inline void read(T &tmp,Args &...tmps){read(tmp);read(tmps...);} const int N = 1e6 + 5; int in[N],out[N],n,m,now[N]; vector<int>g[N]; stack<int>s; int flag = 1,cnt[2],st = 1; inline void dfs(int u){ for(int i=now[u];i<g[u].size();i=now[u]){ now[u] = i + 1;//避免重復走 dfs(g[u][i]); } s.push(u);//記錄,也可以手寫棧更快 } signed main(){ read(n,m); for(int i=1;i<=m;++i){ int u,v; read(u,v); g[u].push_back(v); in[v]++; out[u]++; //統計結點入度出度,如果是無向圖統一一個數組記錄度 } for(int i=1;i<=n;++i)sort(g[i].begin(),g[i].end());//題里要字典序,忽略啦~ for(int i=1;i<=n;++i){ if(in[i] != out[i])flag = 0; if(out[i] == in[i] + 1)cnt[1]++,st = i; if(in[i] == out[i] + 1)cnt[0]++; } if((!flag) && !(cnt[0] == cnt[1] && cnt[0] == 1))return printf("No"),0;//既沒有回路也沒有路徑 dfs(st); while(!s.empty())printf("%d ",s.top()),s.pop();//輸出 }
代碼比較丑啦,但是精髓還在。
#include<cstdio> #include<stack> #include<cstring> #include<algorithm> #include<vector> #define rep(i,a,b) for(register int i=(a);i<=(b);++i) #define Rep(i,a,b) for(register int i=(a);i<(b);++i) #define rrep(i,a,b) for(register int i=(a);i>=b;--i) using namespace std; template <typename T> inline void read(T &x){ x=0;char ch=getchar();bool f=0; while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();} while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); if(f)x=-x; } template <typename T,typename ...Args> inline void read(T &tmp,Args &...tmps){read(tmp);read(tmps...);} const int N = 55; int g[N][N],t,n,du[N]; struct qwq{ int u,v; }; stack<qwq>s; int st; inline void init(){ while(!s.empty())s.pop(); memset(g,0,sizeof(g)); memset(du,0,sizeof(du)); } void dfs(int cur){ rep(i,1,50){ if(g[cur][i]){ g[cur][i]--,g[i][cur]--; dfs(i); s.push((qwq){cur,i}); } } } inline int solve(){ int ji = 0; rep(i,1,50){ ji += du[i]&1; } if(ji)return 0; dfs(st); return 1; } signed main(){ read(t); rep(i,1,t){ read(n); st = 0; rep(j,1,n){ int u,v; read(u,v); g[u][v]++,g[v][u]++; du[u]++,du[v]++; if(!st)st = u; } printf("Case #%d\n",i); if(!solve())puts("some beads may be lost"); else while(!s.empty())printf("%d %d\n",s.top().u,s.top().v),s.pop(); putchar('\n'); init(); } }