给定一张图,请你找出欧拉回路,即在图中找一个环使得每条边都在环上出现恰好一次。输入格式第一行包含一个整数 tt
,t∈{1,2}t∈{1,2}
,如果 t=1t=1
,表示所给图为无向图,如果 t=2t=2
,表示所给图为有向图。第二行包含两个整数 n,mn,m
,表示图的结点数和边数。接下来 mm
行中,第 ii
行两个整数 vi,uivi,ui
,表示第 ii
条边(从 11
开始编号)。如果 t=1t=1
则表示 vivi
到 uiui
有一条无向边。如果 t=2t=2
则表示 vivi
到 uiui
有一条有向边。图中可能有重边也可能有自环。点的编号从 11
到 nn
。输出格式如果无法一笔画出欧拉回路,则输出一行:NO。否则,输出一行:YES,接下来一行输出 任意一组 合法方案即可。如果 t=1t=1
,输出 mm
个整数 p1,p2,…,pmp1,p2,…,pm
。令 e=|pi|e=|pi|
,那么 ee
表示经过的第 ii
条边的编号。如果 pipi
为正数表示从 veve
走到 ueue
,否则表示从 ueue
走到 veve
。如果 t=2t=2
,输出 mm
个整数 p1,p2,…,pmp1,p2,…,pm
。其中 pipi
表示经过的第 ii
条边的编号。数据范围1≤n≤1051≤n≤105
,
0≤m≤2×1050≤m≤2×105
输入样例1:1
3 3
1 2
2 3
1 3
输出样例1:YES
1 2 -3
输入样例2:2
5 6
2 3
2 5
3 4
1 2
4 2
5 1
输出样例2:YES
4 1 3 5 2 6
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010, M = 400010;
int type;
int n, m;
int h[N], e[M], ne[M], idx;
bool used[M];
int ans[M], 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){
for (int &i = h[u]; ~i;){
if (used[i]){
i = ne[i];
continue;
}
used[i] = true;
if (type == 1) used[i ^ 1] = true;
int t;
if (type == 1){
t = i / 2 + 1;
if (i & 1) t = -t;
}
else t = i + 1;
int j = e[i];
i = ne[i];
dfs(j);
ans[++ cnt] = t;
}
}
int 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[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;
}
}
for (int i = 1; i <= n; i ++)
if (h[i] != -1){
dfs(i);
break;
}
if (cnt < m){
puts("NO");
return 0;
}
puts("YES");
for (int i = cnt; i; i --) printf("%d ", ans[i]);
return 0;
}