欧拉路径(Hierholzer 算法)
有向图
https://www.luogu.com.cn/problem/P7771
题意概述
给定一个弱连通有向图,求字典序最小的欧拉路径。
思路
有向图判定是否存在欧拉路径:
1.删去孤立点(入度与出度均为 \(0\)),剩下的点形成的图弱连通。
2.如果所有点的入度 \(=\) 出度,存在欧拉回路,可以任取起点。
3.仅存在一个点出度 \(=\) 入度 \(+1\),该点作为起点;仅存在一个点入度 \(=\) 出度 \(+1\),该点作为终点;其他点入度 \(=\) 出度。
4.其他情况不存在欧拉路径。
由于要求字典序最小,需要对边集排序。
代码
//author:kzssCCC
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void solve(){
int n,m;
cin >> n >> m;
vector<vector<int>> adj(n+1);
vector<int> ing(n+1),oug(n+1);
for (int i=0;i<m;i++){
int u,v;
cin >> u >> v;
adj[u].push_back(v);
ing[v]++,oug[u]++;
}
for (int i=1;i<=n;i++){
sort(adj[i].begin(),adj[i].end());
}
int s=-1,t=-1;
for (int i=1;i<=n;i++){
if (ing[i]!=oug[i]){
if (ing[i]+1==oug[i] && s==-1){
s = i;
}
else if (ing[i]==oug[i]+1 && t==-1){
t = i;
}
else{
cout << "No" << '\n';
return;
}
}
}
if ((s==-1)^(t==-1)){
cout << "No" << '\n';
return;
}
if (s==-1){
for (int i=1;i<=n;i++){
if (ing[i]>0){
s = i;
break;
}
}
}
vector<int> res;
vector<int> cur(n+1);
function<void(int)> dfs = [&](int u){
int len = adj[u].size();
while (cur[u]<len){
int v = adj[u][cur[u]++];
dfs(v);
}
res.push_back(u);
};
dfs(s);
reverse(res.begin(),res.end());
for (auto& v:res){
cout << v << ' ';
}
cout << '\n';
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int t = 1;
// cin >> t;
while (t--) solve();
return 0;
}
无向图
https://www.luogu.com.cn/problem/P2731
题意概述
给定一个连通无向图,求字典序最小的欧拉路径。
思路
无向图判定是否存在欧拉路径:
1.删去孤立点(入度与出度均为 \(0\)),剩下的点形成的图连通。
2.如果所有点度数均为偶数,存在欧拉回路,可以任取起点。
3.恰好存在 \(2\) 个度数为奇数的点,存在欧拉路径,两个点分别作为起点和终点。
4.其他情况不存在欧拉路径。
同样对边集排序。
实现上,由于为无向图,邻接表要需存边的序号以保证不走同样的边。
代码
//author:kzssCCC
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void solve(){
const int n = 500;
int m;
cin >> m;
vector<vector<pair<int,int>>> adj(n+1);
vector<int> deg(n+1);
for (int i=0;i<m;i++){
int u,v;
cin >> u >> v;
adj[u].emplace_back(v,i);
adj[v].emplace_back(u,i);
deg[u]++,deg[v]++;
}
for (int i=1;i<=n;i++){
sort(adj[i].begin(),adj[i].end());
}
int s = -1;
for (int i=1;i<=n;i++){
if (deg[i]&1){
s = i;
break;
}
}
if (s==-1){
for (int i=1;i<=n;i++){
if (deg[i]>0){
s = i;
break;
}
}
}
vector<int> res;
vector<int> cur(n+1);
vector<bool> vis(m,false);
function<void(int)> dfs = [&](int u){
int len = adj[u].size();
while (cur[u]<len){
auto& [v,id] = adj[u][cur[u]++];
if (!vis[id]){
vis[id] = true;
dfs(v);
}
}
res.push_back(u);
};
dfs(s);
reverse(res.begin(),res.end());
for (auto& v:res){
cout << v << '\n';
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int t = 1;
// cin >> t;
while (t--) solve();
return 0;
}

浙公网安备 33010602011771号