欧拉图
欧拉路径
对于一个图,走过每条边且仅走过一次的路径,不一定走过每个点。
欧拉回路
起点和终点相同的欧拉路径。
欧拉图
所有边都在同一条欧拉路径上的图。
判定方法
- 对于有向图,要么所有点的入度都等于出度(存在一个欧拉回路),要么存在且仅存在两个点,一个入度比出度大1,一个出度比入度大1(存在一条不是回路的欧拉路径)。
- 对于无向图,要么所有点的度数均是偶数(欧拉回路),要么存在且仅存在两个点的度数是奇数,其余均为偶数(一条不是回路的欧拉路径)
实现方法
将栈中元素依次弹出,即得一条欧拉路径(回路)
例题
因为题目中要求输出字典序最小的欧拉回路,因此选择编号最小的点作为起点,通过排序使其总是先访问编号较小的点。
代码
| #include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 1E5 + 10;
int n, m;
vector<int> adj[N];
int cur[N];
int ind[N], otd[N];
int sta[N], top;
void dfs(int u) {
for(int i = cur[u]; i < (int)adj[u].size(); i = max(i + 1, cur[u])) {
cur[u]++;
dfs(adj[u][i]);
}
sta[++top] = u;
}
int main() {
cin >> n >> m;
for(int i = 1; i <= m; i++) {
int u, v;
cin >> u >> v;
adj[u].push_back(v);
ind[v]++;
otd[u]++;
}
for(int i = 1; i <= n; i++) {
sort(adj[i].begin(), adj[i].end());
}
bool flag = true;
int beg = 0, end = 0;
for(int i = 1; i <= n; i++) {
if(ind[i] != otd[i]) flag = false;
if(ind[i] == otd[i] + 1) {
if(end != 0) end = -1;
else end = i;
} else if(ind[i] + 1 == otd[i]) {
if(beg != 0) beg = -1;
else beg = i;
} else if(ind[i] != otd[i]) {
beg = end = -1;
}
}
if(!flag && !(beg > 0 && end > 0)) {
cout << "No" << endl;
return 0;
}
if(flag) beg = 1;
dfs(beg);
while(top > 0) {
cout << sta[top--] << ' ';
}
cout << endl;
return 0;
}
|