You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

100 lines
3.6 KiB

2 years ago
#include <bits/stdc++.h>
using namespace std;
const int N = 100010, M = 400010;
int T; // 1无向图2有向图
int n, m; // n个节点m条边
int din[N], dout[N]; // 入度,出度,如果是无向图则din[u]+dout[u]=u点的度
int cnt, ans[M]; // 欧拉回路路径
// 链式前向星
int e[M], h[N], idx, w[M], ne[M];
void add(int a, int b, int c = 0) {
e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}
int st[M]; // 某条边是否已访问过
// 1、无向图
void dfs1(int u) {
for (int i = h[u]; ~i; i = h[u]) {
h[u] = ne[i];
if (st[i]) continue; // 这个st[i]是给成对变换的无向图专用的,因为一边走一边删边,有向图的边都删除掉了,还记录啥走没走过,只有无向图才有这个,因为成对变换的边还没有删除掉,需要标识一下
// st[i] = 1, st[i ^ 1] = 1; // 无向图,成对变换的边也标识为已使用过
st[i ^ 1] = 1; // 无向图,成对变换的边也标识为已使用过
// 本题的特殊要求
int t = i / 2 + 1; // 无向图计算边号注意i从0开始所以需要除2再加1
if (i & 1) t = -t; // 偶数边u->v,奇数边v->u,题目要求v->u输出一个负号
// 注意是回溯时再记录,题解中有论述原因
dfs1(e[i]);
// 记录路径
ans[++cnt] = t;
}
}
// 2、有向图
void dfs2(int u) {
for (int i = h[u]; ~i; i = h[u]) {
h[u] = ne[i];
int t = i + 1; // 有向图计算边号注意i从0开始所以加1
// 注意是回溯时再记录,题解中有论述原因
dfs2(e[i]);
// 记录路径
ans[++cnt] = t;
}
}
int main() {
scanf("%d%d%d", &T, &n, &m); // 图的类型
memset(h, -1, sizeof h); // 链式前向星
for (int i = 0; i < m; i++) { // 后面的m条数是有用的如果路径中最终的数量小于m表示未能找到欧拉回路不能用while(m--)替换
int a, b;
scanf("%d%d", &a, &b);
add(a, b);
if (T == 1) add(b, a);
din[b]++, dout[a]++; // 有向图记录入度和出度无向图D(u)指经过u的无向边数量=din[u]+dout[u]
}
if (T == 1) {
for (int i = 1; i <= n; i++)
if ((din[i] + dout[i]) & 1) { // 无向图中,如果某个点的度是奇数,则不存在欧拉回路
puts("NO");
return 0;
}
} else {
for (int i = 1; i <= n; i++)
if (din[i] != dout[i]) { // 有向图中,如果某个点的入度与出度不等,则不存在欧拉回路
puts("NO");
return 0;
}
}
// 开始找欧拉回路
for (int u = 1; u <= n; u++)
// 举例:如果是两个欧拉回路图,那么两者之间彼此不连通,此时也不欧拉回路,我们找到一个非独立点开始出发,找出所有的边,
// 再通过检查边的数量与真实边的数量对比,才能真正知道是不是存在欧拉回路
if (~h[u]) {
if (T == 1)
dfs1(u);
else if (T == 2)
dfs2(u);
break;
}
// 如果找到的欧拉回路路径条数小于总边数m,表示没有找出全部边,说明无欧拉回路
if (cnt < m) {
puts("NO");
return 0;
}
// 存在欧拉回路
puts("YES");
// 逆序输出序列
for (int i = cnt; i; i--) printf("%d ", ans[i]);
return 0;
}