一.歐拉回路的判定
主要分為兩大類
無向圖歐拉回路判定:
1、歐拉路徑:即可以一筆畫,充要條件是度數為奇數的點的個數為0或2。
2、歐拉回路:歐拉路徑構成一個圈,充要條件是全部是偶點
有向圖歐拉回路判定
1、歐拉路徑:起點出度比入度大1,終點入度比出度大1,其他點全部是偶點
2、歐拉回路:每個點出度和入度都相等,且存在一系列環可以覆蓋原圖。
題目 hihocoder1176
#include <iostream> #include <cstdio> #include <vector> using namespace std; const int maxn = 1e5 + 100; int in[maxn]; int main() { int n, m, x, y; cin>>n>>m; for(int i = 1; i <= m; i++){ cin>>x>>y; in[x]++; in[y]++; } int t = 0; for(int i = 1; i <= n; i++) if(in[i]&1) t++; if(t == 0 || t == 2) cout<<"Full"; else cout<<"Part"; }
二、歐拉路徑的求法
使用Fleury算法求
原理,先找到起點(根據判定)
然后由起點找到dfs出一條路徑L1,那么L1的終點必定是判定里說的終點,於是把L1上所有的邊刪掉,我們再進行增廣
對於L1上每一個點,如果它仍然可以連向其他點,那么就可以繼續走,以歐拉回路的方式再次回到這個點
在這個過程中可能會再次形成L1'回路,然后對L1'回路繼續這樣做,遞歸下去即可
最后按照棧的方式輸出就可以了,利用dfs的性質可以很簡單的做到
hihocoder 1181
#include <iostream> #include <cstdio> #include <vector> #define fi first #define se second using namespace std; const int maxn = 1e5 + 100; typedef pair<int, int> PII; vector<int> G[maxn], V; vector<PII> edges; int f[maxn]; void dfs(int x){ for(auto i : G[x]){ auto e = edges[i]; if(f[i]) continue; f[i] = 1; dfs(e.fi == x ? e.se : e.fi); } cout<<x<<" "; } int main() { int n, m, x, y; cin>>n>>m; for(int i = 1; i <= m; i++){ cin>>x>>y; edges.push_back({x, y}); G[x].push_back(i-1); G[y].push_back(i-1); } for(int i = 1; i <= n; i++) if(G[i].size() & 1) V.push_back(i); int s = V.size() ? V[0] : 1; dfs(s); return 0; }
三、簡單應用
hihocoder 1182
求一個長度為2^n的字符串,使他的每n位恰好構成0~2^n-1
比如說n=3時, 答案為 00010111
即000,001,010,101,011,111,110,100
建圖,比如說001就建(00)->(01), 011建(01)->(11),然后走完所有的邊,實際上就構造了一個歐拉回路
#include <iostream> #include <cstdio> #include <vector> #include <algorithm> #define fi first #define se second using namespace std; const int maxn = (1<<15) + 100; typedef pair<int, int> PII; vector<int> G[maxn], ans; vector<PII> edges; int f[maxn]; int n; void dfs(int x){ for(auto i : G[x]){ if(f[i]) continue; f[i] = 1; dfs(edges[i].se); } ans.push_back(x); } int main() { cin>>n; if(n == 1) { cout<<"01"<<endl; return 0; } for(int i = 0; i < (1<<n); i++){ int y = i&((1<<(n-1))-1), x = i>>1; edges.push_back({x, y}); G[x].push_back(edges.size()-1); } dfs(0); reverse(ans.begin(), ans.end()); for(int i = 1<<(n-1); i >= 1; i >>= 1){ if(i&ans[1]) cout<<"1"; else cout<<"0"; } for(int i = 2; i < ans.size()-n+1; i++){ if(ans[i]&1) cout<<"1"; else cout<<"0"; } }
00010111
