1.定义
通俗的讲,欧拉回路是从图上某一点出发,经过一系列不重复的边,然后再回到开始节点的路径。
注意,这个过程可以经过重复的节点 比如图中仅有一个点,有 (998244353) 个自环,但这些自环仍然可以构成欧拉回路。
2.存在条件
- 有向图
每个节点入度等于出度 - 无向图
每个节点度均为偶数
3.求解方法
比较简单,从一个点出发进行dfs,在回溯的时候把当前边加入答案队列。
但有以下情况需要考虑
- 图不连通
无解。前提是至少两个连通块内有边 - 单独一个点
可以忽略,不对答案产生影响。因为欧拉回路关心的是经过所有边 单独一个点不会影响答案 - 优化
如果不加当前弧优化,复杂度是 (O(nm))
加上后能优化到 (O(n+m))
4.例题&代码
模板-UOJ117
分别对有向图和无向图找出欧拉回路,输出路径。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<map>
#include<cstring>
#include<stack>
#include<queue>
#include<vector>
#include<bitset>
#define ll long long
using namespace std;
const int inf = 0x7fffffff;
int T,n,m;
#define maxn 400009
int in[maxn],ans[maxn],out[maxn];
int nxt[maxn],head[maxn],to[maxn];
bool ban[maxn],vis[maxn];
namespace fuckccf//无向边
{
int num=0,cnt=1;//!!!从1开始记录
void Add(int x,int y){cnt++;nxt[cnt]=head[x];to[cnt]=y;head[x]=cnt;}//邻接表
void dfs(int x)
{
ban[x]=1;
for(int &i=head[x];i;i=nxt[i])//当前弧
{
int t=to[i],j=i>>1,val=i;//!!!进行完dfs之后i的值会改变 要提前存下来
if(vis[j])continue;
vis[j]=1;
dfs(t);
num++;
if(val&1)ans[num]=-j;//如果是正向的 i末尾是0 否则是1
else ans[num]=j;
}
}
void main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
Add(x,y);
Add(y,x);
in[x]++;
in[y]++;
}
for(int i=1;i<=n;i++)if(in[i]&1){printf("NO
");return;}//判断无解
for(int i=1;i<=n;i++)
{
if(!ban[i])dfs(i);
if(num&&num<m)//走了一些边,但没走完,说明图不连通或者无解
{
printf("NO
");
return;
}
}
printf("YES
");
for(int i=m;i>=1;i--)
{
printf("%d ",ans[i]);
}
}
}
namespace tymXINzhy//有向边
{
int num=0,cnt=0;
void Add(int x,int y){cnt++;nxt[cnt]=head[x];to[cnt]=y;head[x]=cnt;}
void dfs(int x)
{
ban[x]=1;
for(int &i=head[x];i;i=nxt[i])
{
int t=to[i],val=i;
if(vis[i])continue;
vis[i]=1;
dfs(t);
num++;
ans[num]=val;//直接记录边即可
}
}
void main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
Add(x,y);
in[y]++;
out[x]++;
}
for(int i=1;i<=n;i++)if(in[i]!=out[i]){printf("NO
");return;}
for(int i=1;i<=n;i++)
{
if(!ban[i])dfs(i);
if(num&&num<m)
{
printf("NO
");
return;
}
}
printf("YES
");
for(int i=m;i>=1;i--)
{
printf("%d ",ans[i]);
}
}
}
signed main()
{
// freopen("h.in","r",stdin);
scanf("%d",&T);
if(T==1)fuckccf::main();
else tymXINzhy::main();
return 0;
}
`