AcWing 1184. 欧拉回路模板
原题链接
简单
作者:
Tizzi
,
2020-02-17 20:59:20
,
所有人可见
,
阅读 1320
#include <cstdio>
const int N = 1e5 + 5, M = 4e5 + 5;
struct E {
int v, next;
} e[M];
int t, n, m, cnt, len, u, v, h[N], ind[N], outd[N], path[M];
bool vis[M]; //代表某条边是否被使用过
void add(int u, int v) {
e[++len].v = v; e[len].next = h[u]; h[u] = len;
}
bool ok() {
if (t == 1) {
for (int i = 1; i <= n; i++) {
if ((ind[i] + outd[i]) & 1) return false;
}
} else {
for (int i = 1; i <= n; i++) {
if (ind[i] != outd[i]) return false;
}
}
return true;
}
void dfs(int u) {
//变成引用 等于删除这条边 用完就删
for (int &j = h[u]; j; j = e[j].next) {
if (vis[j]) continue;
vis[j] = true;
if (t == 1) vis[j ^ 1] = true; //无向图的反向边
//由于要删除边 所以记录编号
int no = t == 1 ? j / 2 : j - 1; //如果是无向边的话 边数为/ 2
if (t == 1 && (j & 1)) no = -no;
int v = e[j].v;
dfs(v);
path[++cnt] = no;
}
}
int main() {
scanf("%d%d%d", &t, &n, &m); len = 1; //节点编号从2开始
for (int i = 1; i <= m; i++) {
scanf("%d%d", &u, &v);
add(u, v);
if (t == 1) add(v, u);
ind[v]++, outd[u]++;
}
//判断是否有解
if (!ok()) printf("NO");
else {
//判断是否找到回路
for (int i = 1; i <= n; i++) {
if (h[i]) { //代表不是孤立点
dfs(i);
break;
}
}
if (cnt != m) printf("NO");
else {
printf("YES\n");
for (int i = cnt; i > 0; i--) printf("%d ", path[i]);
}
}
return 0;
}