欧拉回路:通过图中每条边恰好一次的回路
欧拉通路:通过图中每条边恰好一次的通路
欧拉图:具有欧拉回路的图
半欧拉图:具有欧拉通路但不具有欧拉回路的图
// n点m边,可重边自边
int n, m;
cin >> n >> m;
vector<int> deg(n), del(m); // deg[i]点i的度,del[i]编号i的边是否删除
vector<vector<pair<int,int>>> g(n); // g[i] i的出边 连接点和编号
for (int i=0; i<m; i++) {
int x, y;
cin >> x >> y;
deg[x]++;
deg[y]++;
g[x].emplace_back(y, i);
g[y].emplace_back(x, i);
}
vector<int> stk; // 欧拉通路/回路所经过的点,若为有向图则是逆序
function<void(int)> euler = [&](int u) {
while(g[u].size()) {
auto [v, e] = g[u].back();
g[u].pop_back();
if (del[e]) continue;
del[e] = 1;
euler(v);
}
stk.push_back(u);
};
// deg 只存在两个奇数,其余为偶数,则存在欧拉通路
// deg 只存在偶数,则存在欧拉回路
for (int i=0; i<n; i++) {
if (deg[i]%2) {
euler(i); // 欧拉通路从奇数度开始
break;
}
}
if (stk.empty()) euler(0); // 不存在奇数度,欧拉回路可从任意一点开始
for (int i:stk) {
cout << i << " ";
}
cout << "\\n";
// n点m边,可重边自边
int n, m;
cin >> n >> m;
vector<int> deg(n), del(m); // deg[i] 点i的出度-入度,del[i]编号i的边是否删除
vector<vector<pair<int,int>>> g(n); // g[i] i的出边 连接点和编号
for (int i=0; i<m; i++) {
int x, y;
cin >> x >> y;
deg[x]++;
deg[y]--;
g[x].emplace_back(y, i);
}
vector<int> stk; // 欧拉通路/回路所经过的点,若为有向图则是逆序
function<void(int)> euler = [&](int u) {
while(g[u].size()) {
auto [v, e] = g[u].back();
g[u].pop_back();
if (del[e]) continue;
del[e] = 1;
euler(v);
}
stk.push_back(u);
};
// deg 只存在一个1和-1,其余为0,则存在欧拉通路
// deg 只存在0,则存在欧拉回路
for (int i=0; i<n; i++) {
if (deg[i] == 1) {
euler(i); // 欧拉通路从出度-入度=1开始
break;
}
}
if (stk.empty()) euler(0); // 不存在奇数度,欧拉回路可从任意一点开始
reverse(stk.begin(), stk.end());
for (int i:stk) {
cout << i << " ";
}
cout << "\\n";