欧拉回路
作者:互联网
七桥问题
定义 如果图G(有向图或者无向图)中所有边一次仅且一次性遍所有顶点的通路称作欧拉通路。 如果图G中所有边一次仅且一次行遍所有顶点的回路称作欧拉回路。 具有欧拉回路的图称为欧拉图(简称E图)。具有欧拉通路但不具有欧拉回路的图称为半欧拉图。欧拉图上的欧拉路径一定是回路 判断 首先是个连通图如果所有的点的度数都为偶数,那么这是一条欧拉回路
如果存在两个奇度点,那么从一个奇度点出发,最后到达另一个奇点,则称这是一条欧拉道路。
无向图存在欧拉回路的充要条件:
一个无向图存在欧拉回路,当且仅当该图所有顶点度数都为偶数,且该图是连通图。
有向图存在欧拉回路的充要条件:
一个有向图存在欧拉回路,所有顶点的入度等于出度且该图是连通图。
无向图半欧拉图判定
判断:有且仅有两个点度数是奇数
方法:加一条边,找欧拉回路,再删这条边,就找到了欧拉路径
有向图半欧拉图判定
判断:(起点)一个顶点的出度比入度大1,(终点)一个顶点的入度比出度大1,其余顶点入度等于出度
方法:加一条边,找欧拉回路,再删这条边,就找到了欧拉路径
回路的合并
两条回路有交点,可以合并成一条回路
例子:1—>2—>3—>7—>1 & 3—>4—>5—>6—>3
可以想象三自己走到自己 1—>2—>3—>3—>7—>1然后带入第二条回路
合并成功1—>2—>3—>4—>5—>6—>7—>1
欧拉回路的求解
找到剩余的度数不为0的一点
Hierholzer算法
Hierholzer算法是通过不断从图中删去回路的方式,将删去的多个回路和路径最终组合起来成为欧拉回路或欧拉路径。
算法流程如下:
DFS(x){
枚举与x关联的每条边e
删去e (若是无向图还需 删去对应的反向边)
DFS(e.to)
}将x放入栈中
对于无向图,若无奇点则任意从一个点开始执行算法,若恰有两个奇点则从其中一个开始执行算法
对于有向图,若所有点的入度等于出度则从任意一点开始执行算法, 若恰有两个点入度和出度之差等于1则从其中一个开始执行算法
该图是无向图且无奇数度数点,从1开始执行算法,执行过程如下:
1、从节点1开始执行算法
2、删边1-7, 递归DFS(7)
3、删边7-3, 递归DFS(3)
4、删边3-2,递归DFS(2)
5、删边2-1,递归DFS(1)
6、节点1无边,将1放入栈中,返回
7、节点2无边,将2放入栈中,返回
8、删边3-4,递归DFS(4)
9、 删边4-5,递归DFS(5)
10、 删边5-6,递归DFS(6)
11、删边6-3,递归DFS(3)
12、 节点3无边,将3放入栈中,返回
13、 节点6无边,将6放入栈中,返回
14、节点5无边,将5放入栈中,返回
15、节点4无边,将4放入栈中,返回
16、节点3无边,将3放入栈中,返回
17、节点7无边,将7放入栈中,返回
18、 节点1无边,将1放入栈中,返回
栈中元素自顶至下为: 1,7,3,4,5,6,3,2,1, 恰为一条欧拉回路。
https://www.luogu.com.cn/problem/P2731板子
程序复杂度O(mlogn)
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<stack> 5 using namespace std; 6 #define N 1500 7 stack< int >s; 8 int n,maxn,du[N],ans[N],g[N][N]; 9 void dfs(int u){ 10 for(int v=1;v<=maxn;v++) 11 if(g[u][v]){ 12 g[u][v]--; 13 g[v][u]--; 14 dfs(v); 15 } 16 s.push(u); 17 } 18 int main(){ 19 scanf("%d",&n); 20 for(int i=1,x,y;i<=n;i++){ 21 scanf("%d%d",&x,&y); 22 maxn=max(maxn,x); 23 maxn=max(maxn,y); 24 g[x][y]++; 25 g[y][x]++; 26 du[x]++; 27 du[y]++; 28 } 29 int st=1; 30 for(int i=1;i<=maxn;i++) 31 if(du[i]%2){ 32 st=i;break; 33 } 34 dfs(st); 35 while(!s.empty()){ 36 printf("%d\n",s.top()); 37 s.pop(); 38 } 39 return 0; 40 }欧拉回路
标签:回路,DFS,栈中,删边,节点,欧拉 来源: https://www.cnblogs.com/liukx/p/12520129.html