欧拉回路算法
一.欧拉回路的判定
主要分为两大类
无向图欧拉回路判定:
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