定义
如果图G中的一个路径包括每个边恰好一次,则该路径称为欧拉路径(Euler path)。
如果一个回路是欧拉路径,则称为欧拉回路(Euler circuit)。
具有欧拉回路的图称为欧拉图(简称E图)。具有欧拉路径但不具有欧拉回路的图称为半欧拉图。
判定
有向图回路:图联通
&
&
\&\&
&& 每个点入度
=
=
= 出度
无向图回路:图联通
&
&
\&\&
&& 每个点的度数为偶数
有向图通路:图联通
&
&
\&\&
&& 每个点入度
=
=
= 出度
或者可以存在两个点,其中一个出度比入度大
1
1
1,为路径的起点
另外一个入度比出度大
1
1
1,为路径的终点
无向图通路:图联通
&
&
\&\&
&& 度数为奇数的的点只有
2
2
2 个或者
0
0
0 个
当有两个奇点时,一个为起点,另一个为终点
欧拉回路 输出
从起点开始找一条回路
找出有尚未访问的边的路径上的第一个顶点, 并执行另外一次深度优先搜索
这将给出另外一个回路, 把它拼接到原来的回路上
继续该过程直到所有的边都被遍历为止
模板题:UOJ #117. 欧拉回路
s
o
l
v
e
1
solve1
solve1 为无向图回路,
s
o
l
v
e
2
solve2
solve2 为有向图回路
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
const int maxn = 1e6 + 5;
int T, n, m;
bool solve1() { // 无向图
scanf("%d%d", &n, &m);
vector <vector <pii> > g(2 * n + 5);
for(int i=1, u, v; i<=m; i++) {
scanf("%d%d", &u, &v);
g[u].push_back({v, i});
g[v].push_back({u, -i});
}
for(int i=1; i<=n; i++)
if(g[i].size() & 1) return printf("NO\n"), 0;
vector <bool> del(m + 5);
vector <int> ans;
function <void(int, int)> dfs = [&] (int u, int fa) {
while(g[u].size()) {
auto it = g[u].back(); g[u].pop_back();
int v = it.first, id = it.second;
if(!del[abs(id)]) {
del[abs(id)] = true;
dfs(v, id);
}
}
if(fa != 0) ans.push_back(fa);
};
for(int i=1; i<=n; i++)
if(g[i].size()) {
dfs(i, 0);
break;
}
if(ans.size() != m) return printf("NO\n"), 0;
printf("YES\n");
for(int i=ans.size()-1; ~i; i--)
printf("%d ", ans[i]);
}
bool solve2() { // 有向图
scanf("%d%d", &n, &m);
vector <int> in(n + 5), out(n + 5);
vector <vector <pii> > g(2 * n + 5);
for(int i=1, u, v; i<=m; i++) {
scanf("%d%d", &u, &v);
g[u].push_back({v, i});
in[v]++, out[u]++;
}
for(int i=1; i<=n; i++)
if(in[i] ^ out[i]) return printf("NO\n"), 0;
vector <bool> del(m + 5);
vector <int> ans;
function <void(int, int)> dfs = [&] (int u, int fa) {
while(g[u].size()) {
auto it = g[u].back(); g[u].pop_back();
int v = it.first, id = it.second;
if(!del[id]) {
del[id] = true;
dfs(v, id);
};
}
if(fa != 0) ans.push_back(fa);
};
for(int i=1; i<=n; i++)
if(g[i].size()) {
dfs(i, 0);
break;
}
if(ans.size() != m) return printf("NO\n"), 0;
printf("YES\n");
for(int i=ans.size()-1; ~i; i--)
printf("%d ", ans[i]);
}
signed main() {
scanf("%d", &T);
T == 1 ? solve1() : solve2();
}
欧拉通路 输出
模板题:HihoCoder - 1181
输出欧拉路径(无向图)
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
const int maxn = 1e6 + 5;
int T, n, m;
signed main() {
scanf("%d%d", &n, &m);
vector <vector <pii> > g(2 * n + 5);
for(int i=1, u, v; i<=m; i++) {
scanf("%d%d", &u, &v);
g[u].push_back({v, i});
g[v].push_back({u, -i});
}
int st = 1;
for(int i=1; i<=n; i++)
if(g[i].size() & 1) st = i;
vector <bool> del(m + 5);
vector <int> ans;
function <void(int, int)> dfs = [&] (int u, int fa) {
while(g[u].size()) {
auto it = g[u].back(); g[u].pop_back();
int v = it.first, id = it.second;
if(!del[abs(id)]) {
del[abs(id)] = true;
dfs(v, id);
}
}
ans.push_back(u);
};
for(int i=1; i<=n; i++)
if(g[i].size()) {
dfs(st, 0);
break;
}
for(int i=ans.size()-1; ~i; i--)
printf("%d ", ans[i]);
}