欧拉回路模板
作者:
acvv_bdxgd
,
2020-12-18 14:30:57
,
所有人可见
,
阅读 646
#include<bits/stdc++.h>
using namespace std;
const int N = 100010, M = 400010;
int t; // 类型 无向边/ 有向边
int n, m; // 点和边的数量
int din[N], dout[N]; // 分别表示入度和出度
int h[N], e[M], ne[M], idx, cnt;
bool used[M];
int ans[M];
void add(int a, int b){ // 把临边串成一个链表
e[idx]=b, ne[idx]=h[a], h[a]=idx++;
}
// 无欧拉回路的情况
// 1. 不连通
// 2. 不满足各自的性质
// 背过,为了防止自环,代码稍难理解一些,全局h[u]可以理解为引用/////////////////////
// 无向图
void dfs(int u){
// 遍历这个点的所有临点,查重,删除边,dfs,加点
while(~h[u]){ // h[u] 表示当前可用的第一条边
// 无向图需要额外查重
if(used[h[u]]){
h[u]=ne[h[u]];
continue;
}
used[h[u]^1]=true;
// 保留当前边后,删边!
int i=h[u];
h[u]=ne[i]; // 删边
// dfs
dfs(e[i]);
// 加边
int tmp;
tmp=i/2+1;
if(i&1) tmp*=-1;
ans[cnt++]=tmp;
}
}
// 有向图
void dfs1(int u){
// 遍历这个点的所有临点,删除边,dfs,加点
while(~h[u]){ // h[u] 表示当前可用的第一条边
// 保留当前边后,删边!
int i=h[u];
h[u]=ne[i]; // 删边
// dfs
dfs1(e[i]);
// 加边
ans[cnt++]=i+1;
}
}
///////////////////////////////////////////////////////////////
int main(){
memset(h, -1, sizeof h);
cin>>t>>n>>m;
for(int i=0;i<m;i++){
int a, b;
scanf("%d%d", &a, &b);
add(a, b);
if(t==1) add(b, a);
din[b]++, dout[a]++;
}
// 是否满足 无向图/有向图 各自的性质
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 i=1;i<=n;i++)
if(h[i]!=-1){
if(t!=1) dfs1(i); // 有向边
else dfs(i);
break;
}
// cout<<cnt<<" "<<m<<endl;
if(cnt<m){
puts("NO");
return 0;
}
// hh
puts("YES");
// 打印路径
for(int i=cnt-1;i>=0;i--) printf("%d ", ans[i]);
return 0;
}