题目传送门
- 本题数据量较小,可以使用邻接矩阵
- 要求输出最小字典序,我们需要保证由小点出发,一路上从小枚举到大
- 考查无向图求欧拉路径的办法
一、邻接矩阵模板
#include <bits/stdc++.h>
using namespace std;
const int N = 510;
int n = 500, m;
int g[N][N]; //邻接矩阵
vector<int> path; //欧拉路径
int d[N]; //度数
void dfs(int u) {
//我们在遍历的时候,把走过的路删掉,这样就不会重复走了,而且省去了反复横跳的风险
for (int i = 1; i <= n; i++) //枚举每个点
if (g[u][i]) { //如果u->i存在一条边
g[u][i]--, g[i][u]--; //那么我们删除掉正向边和反向边
dfs(i); //继续搜索
}
path.push_back(u); //记录这个点
}
int main() {
cin >> m;
while (m--) {
int a, b;
cin >> a >> b;
g[a][b]++, g[b][a]++; //邻接矩阵记录无向边
d[a]++, d[b]++; //记录无向图的度数
}
//下面这样去费劲找到第一个可行的度数为奇数的点,是为了最小字典序
//较小编号作为起点
int start = 1; //默认从1号点出发
while (!d[start]) start++; //如果是孤立点,那么继续尝试其它点
for (int i = 1; i <= n; i++) //尝试找到度数为奇数的点
if (d[i] % 2) {
start = i;
break;
}
//无向图开始查找欧拉路径
dfs(start);
//输出欧拉路径
for (int i = path.size() - 1; i >= 0; i--) printf("%d\n", path[i]);
return 0;
}
二、邻接表解法
#include <bits/stdc++.h>
using namespace std;
const int N = 5e3 + 10;
typedef pair<int, int> PII;
int n = 500, m;
vector<int> path;
bool st[N];
int d[N];
int h[N], e[N], ne[N], idx;
void add(int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
void dfs(int u) {
vector<PII> a;
for (int i = h[u]; ~i; i = ne[i]) a.push_back({e[i], i});
sort(a.begin(), a.end()); //从小到大排序
for (int i = 0; i < a.size(); i++) {
int edge = a[i].second;
if (st[edge] || st[edge ^ 1]) continue;
st[edge] = st[edge ^ 1] = true;
dfs(a[i].first);
}
path.push_back(u);
}
int main() {
memset(h, -1, sizeof h);
cin >> m;
while (m--) {
int a, b;
cin >> a >> b;
add(a, b), add(b, a);
d[a]++, d[b]++;
}
int start = 1;
while (!d[start]) start++;
for (int i = 1; i <= n; i++)
if (d[i] & 1) {
start = i;
break;
}
dfs(start);
for (int i = path.size() - 1; i >= 0; i--) cout << path[i] << endl;
return 0;
}