欧拉回路
定义
图中经过所有边恰好一次的路径叫欧拉路径.
如果此路径的起点和终点相同,则称其为一条欧拉回路.
有向图欧拉路径
1. 恰好存在 $\mathrm{1}$ 个点出度比入度多 $\mathrm{1}$ (这个点即为起点 $\mathrm{s}$)
2. 恰好存在 $\mathrm{1}$ 个点入度比出度多 $\mathrm{1}$ (这个点即为终点 $\mathrm{t}$)
3. 其余节点出度 $\mathrm{=}$ 入度
找到起点后对于每个点遍历一个没遍历过的边即可.
开一个 $\mathrm{del[x]}$ 数组表示前 $\mathrm{del[x]}$ 个边已遍历过,然后更新即可.
#include <cstdio> #include <cstring> #include <vector> #include <stack> #include <algorithm> #define N 100009 #define ll long long #define pb push_back #define setIO(s) freopen(s".in","r",stdin) using namespace std; vector<int>G[N]; stack<int>se; int n , m , del[N], deg[N][2]; void dfs(int x) { for(int i = del[x]; i < G[x].size() ; i = del[x]) { ++ del[x]; dfs(G[x][i]); } se.push(x); } int main() { // setIO("input"); scanf("%d%d", &n, &m); for(int i = 1; i <= m ; ++ i) { int x, y; scanf("%d%d", &x, &y); G[x].pb(y); deg[x][1]++; deg[y][0]++; } int flag = 0, s1 = 0, s2 = 0, sta = 1; for(int x = 1; x <= n ; ++ x) { if(deg[x][0] != deg[x][1]) ++ flag; // printf("%d %d %d\n", x, deg[x][0], deg[x][1]); if(deg[x][0] - deg[x][1] == 1) s1 = x; if(deg[x][1] - deg[x][0] == 1) s2 = x; } // printf("%d\n", flag); if((flag == 0) || ((flag == 2) && s1 && s2)) { // 合法 if(s2) sta = s2; for(int i = 1; i <= n ; ++ i) sort(G[i].begin(), G[i].end()); dfs(sta); while(!se.empty()) { printf("%d ", se.top()); se.pop(); } } else { printf("No"); } return 0; }
有向图欧拉回路
1. 所有点出度等于入度
无向图欧拉路径
1. 恰好两个点度数为奇数
2. 其余点度数为偶数
这里面度数为奇数的点就是起点和终点.
和有向图的求法差不多,不过要开一个 $\mathrm{map}$ 记录一条无向边是否被遍历过.
若该边已被定向,则不能继续访问了.
#include <bits/stdc++.h> #define N 100009 #define ll long long #define pb push_back #define mp make_pair #define setIO(s) freopen(s".in","r",stdin) using namespace std; int m , deg[N], del[N]; stack<int>se; vector<int>G[N]; map<pair<int, int>, int>vis; void dfs(int x) { for(int i = del[x]; i < G[x].size() ; i = del[x]) { ++ del[x]; int v = G[x][i]; if(!vis[mp(x, v)]) continue; vis[mp(x, v)] -- ; vis[mp(v, x)] -- ; dfs(v); } se.push(x); } int main() { // setIO("input"); scanf("%d", &m); int st = N; for(int i = 1; i <= m ; ++ i) { int x, y; scanf("%d%d", &x, &y); G[x].pb(y); G[y].pb(x); ++ deg[x], ++ deg[y]; st = min(st, min(x, y)); vis[mp(x, y)] ++ ; vis[mp(y, x)] ++ ; } for(int i = 1; i <= 500; ++ i) { sort(G[i].begin(), G[i].end()); } for(int i = 1; i <= 500; ++ i) { if(deg[i] & 1) { st = i; break; } } dfs(st); while(!se.empty()) { printf("%d\n", se.top()); se.pop(); } return 0; }
无向图欧拉回路
1. 所有点度数为偶数