题目链接:
若不懂欧拉路径的可以看看这篇博客:(1条消息) 欧拉回路总结 + 例题 信息学奥赛 铲雪车 欧拉回路 骑马修栅栏 单词游戏_wsh1931的博客-CSDN博客_欧拉回路例题
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 100010, M = 200010;
int n, m;
int st, ed;
int del[N];//表示已经删除了几条边
int cnt, ans[M];//注意ans村的是边数
int din[N], dout[N];//din, dout分别表示入度和出度
vector<int> map[N];//存边
void dfs(int u)
{
for (int i = del[u]; i < map[u].size(); i = del[u])//del[u]记录的是u这个点被删除了del[u]条边
{
del[u] ++ ;//删除的边数加1
dfs(map[u][i]);//递归下一个点
}
ans[cnt ++ ] = u;
}
int main()
{
cin >> n >> m;
for (int i = 0; i < m; i ++ )
{
int a, b;
scanf("%d %d", &a, &b);
map[a].push_back(b);//从a到b连一条边
dout[a] ++ , din[b] ++ ;//a的出度加一,b的入度加1
}
int u = 1, res = 0;
for (int i = 1; i <= n; i ++ )
{
if (din[i] == dout[i] + 1) ed ++ ;//若入读比出度多一,说明是终点
if (dout[i] == din[i] + 1)//若出度比入度多一说明是起点
{
st ++ ;
u = i;
}
if (din[i] != dout[i]) res ++ ;//记录出度不等于入度的点的数量
}
if (res != 0 && res != 2)//若入度不等于出度的点不是0,2说明无解
{
puts("No");
return 0;
}
if (!res)//当所有点的入度等于出度时即起点等于终点
{
if (ed || st)//ed, st都为0
{
puts("No");
return 0;
}
}
if (res == 2)//起点不等于终点
{
if (ed != 1 && st != 1)//若起点和终点不止一个说明无解
{
puts("No");
return 0;
}
}
for (int i = 1; i <= n; i ++ ) sort(map[i].begin(), map[i].end());//按访问的点从小到大排序
dfs(u);
for (int i = cnt - 1; i >= 0; i -- ) printf("%d ", ans[i]);//因为dfs先遍历后存数,所以要逆序输出
return 0;
}