Euler回路

首先都要判断连通性。

无向图Euler回路

一个无向图有Euler回路\(\Leftrightarrow\)每个点的度数为偶数。
求Euler回路可以采用套圈法。
过程就是dfs,回溯的时候把边加到答案里面去。

有向图Euler回路

一个有向图有Euler回路\(\Leftrightarrow\)每个点的出度等于入度。
求Euler回路过程跟无向图是一样的。

混合图Euler回路

就是有的边是无向边有的边是有向边。
我们先给原图\(G\)中的无向边随便定个向,得到一个新图\(G'\)
那么如果\(G'\)中的任意一个点的出度减入度(记为\(d_i\))为奇数,那么不存在Euler回路。
然后我们建一个图\(G''\)跑网络流。
建一个源点\(S\)和汇点\(T\)
\(\forall d_i>0\)连一条\(S\)\(i\)的容量为\(\frac{d_i}2\)的边。
\(\forall d_i<0\)连一条\(i\)\(T\)的容量为\(\frac{-d_i}2\)的边。
然后把\(G'\)中的所有边加到\(G''\)来,容量为\(1\)
\(G''\)的最大流,如果\(S\)连出去的边都能满流,那么\(G\)存在Euler回路。
正确性很好理解,因为这个\(G''\)的意义就是凑出每个点入度等于出度的无向图。
然后把\(G''\)中在\(G\)中为无向边的流量为\(1\)的边中有流量的边反向,那么就形成了一个能存在Euler回路的有向图。所以要求方案就可以直接在这个有向图上面求了。

例题

UOJ117 欧拉回路
Link

#include<bits/stdc++.h>
using namespace std;
namespace IO
{
    char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[15],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
    char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
    void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;}
    void Put(char x){*oS++=x;if(oS==oT)Flush();}
    int read(){int x=0;char ch=Get();while(ch>57||ch<48)ch=Get();while(ch>=48&&ch<=57)x=x*10+(ch^48),ch=Get();return x;}
    void write(int x){int top=0;if(x<0)Put('-'),x=-x;if(!x)Put('0');while(x)st[++top]=(x%10)+48,x/=10;while(top)Put(st[top--]);Put(' ');}
}
using IO::read;
using IO::write;
#define N 100007
int tot=1,head[N],ver[N<<2],Next[N<<2],deg[N],vis[N<<2],ans[N<<2],num;
void add(int u,int v){ver[++tot]=v,Next[tot]=head[u],head[u]=tot;}
int cal(int x){return x%2? -x/2:x/2;}
void dfs(int u)
{
    int i;
    while(head[u])
	if(!vis[i=head[u]]) vis[i]=vis[i^1]=1,dfs(ver[i]),ans[++num]=cal(i);
	else head[u]=Next[head[u]];
}
int solve1()
{
    int n=read(),m=read(),i,u,v;
    for(i=1;i<=m;++i) u=read(),v=read(),add(u,v),add(v,u),++deg[u],++deg[v];
    for(i=1;i<=n;++i) if(deg[i]%2) return 0;
    for(i=1;i<=n;++i) if(head[i]) {dfs(i);break;}
    if(num^m) return 0;
    puts("YES");
    for(;num;--num) write(ans[num]);
    return 1;
}
void Dfs(int u)
{
    int i;
    while(head[u])
	if(!vis[i=head[u]]) vis[i]=1,Dfs(ver[i]),ans[++num]=i-1;
	else head[u]=Next[head[u]];
}
int solve2()
{
    int n=read(),m=read(),i,u,v;
    for(i=1;i<=m;++i) u=read(),v=read(),add(u,v),--deg[u],++deg[v];
    for(i=1;i<=n;++i) if(deg[i]) return 0;
    for(i=1;i<=n;++i) if(head[i]) {Dfs(i);break;}
    if(num^m) return 0;
    puts("YES");
    for(;num;--num) write(ans[num]);
    return 1;
}
int main()
{
    if(read()==1? solve1():solve2()) return IO::Flush(),0;
    else return !puts("NO");
}
posted @ 2019-11-24 21:27  Shiina_Mashiro  阅读(344)  评论(0编辑  收藏  举报