题目:https://www.acwing.com/problem/content/1186/
题意:
题解:题意很清楚,就是求无向图或者有向图的欧拉回路,然后按照它的格式输出走过的边的编号,,,,这里求边的编号有个技巧,如果是有向图,那么就是边的编号就是idx+1,因为idx是从0开始的;如果是无向图,那么就是idx/2+1,然后再看一下这个值和1&一下,就知道这条边是正向遍历还是反向遍历了。
代码:
#include <bits/stdc++.h>
//#define int long long
#define pb push_back
#define pii pair<int, int>
#define mpr make_pair
#define ms(a, b) memset((a), (b), sizeof(a))
#define x first
#define y second
typedef long long ll;
typedef unsigned long long LL;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
using namespace std;
const int N = 1e5 + 9, M = 4e5 + 10;
int type; //图的类型
int n, m;
int h[N], e[M], ne[M], idx;
bool used[M]; //记录这条边是否走过,用链式前向星中的idx来判断边
int ans[M], cnt; //ans答案,cnt边的数量
int din[N], dout[N]; //入度,出度
void add(int a, int b) { e[idx] = b, ne[idx] = h[a], h[a] = idx++; }
void dfs(int u) {
//i直接引用h[u],当i变的时候,h[u]就变了,就进行了删边
for (int &i = h[u]; ~i;) {
//因为下面的删边操作,这里只是卡住了无向图的反向边不再跑
//有向图的话,通过下面的删边操作,肯定不会再跑
if (used[i]) { //如果这是曾经被跑过边的反向边,则跳过
i=ne[i];
continue;
}
//如果是无向图,则把反向边标记,不再跑
if (type == 1) used[i ^ 1] = true;
//得到这条边应有的编号,
int t;
if (type == 1) {
//无向图,idx/2+1就是第几条边,因为是每次add两条边
t = i / 2 + 1;
//如果是某条边的反向,则为负数(题目要求)
if (i & 1) t = -t;
} else t = i + 1;//有向图i+1就是这条边的编号,idx从0开始的
int j=e[i]; //保存这条边的目的地点,用于下面的dfs,因为要删边
i=ne[i]; //先删边,防止后面的环、自环等等会重复遍历,卡成n^2
//i是h[u]的索引,当i在变的时候,其实就是h[u]在变
dfs(j);
ans[++cnt] = t; //存答案(这里存的是反的)
}
}
signed main() {
scanf("%d", &type);
scanf("%d%d", &n, &m);
memset(h, -1, sizeof(h));
for (int i = 0; i < m; i++) {
int a, b;
scanf("%d%d", &a, &b);
add(a, b);
//如果为无向图就反向建边
if (type == 1) add(b, a);
//无向图度数的时候,din+dout即可
din[b]++, dout[a]++;
}
//无向图判某些无欧拉回路的情况
if (type == 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;
}
}
}
//跑dfs
for (int i = 1; i <= n; i++) {
if (h[i] != -1) {
dfs(i);
break;
}
}
//如果边不连通也是NO
if (cnt < m) {
puts("NO");
return 0;
}
//YES情况
puts("YES");
//存的是反的,再反向输出即可
for (int i = cnt; i; i--) printf("%d ", ans[i]);
puts("");
return 0;
}