「图论」欧拉路

定义

通路:一条从(v_i)(v_j)的不经过重复边的一条路经,长度为通路中边的个数

回路:起点和终点相同的通路

欧拉通路:经过图(G)所有边一次的通路

欧拉回路:经过图(G)所有边一次的回路

欧拉图((E)图):具有欧拉回路的图

半欧拉图:具有欧拉通路但不具有欧拉回路的图

平凡图:只有一个节点的图

判定

无向图:(G)为连通图,有且仅有两个奇数度顶点,则图存在欧拉通路,无奇数度节点,则图存在欧拉回路

有向图:(G)为连通图,起点出度比入度大(1),终点入度比出度大(1),则存在欧拉通路,所有顶点入度等于出度,则存在欧拉回路

证明: 无向图(G)为连通图,无奇数度节点,则图存在欧拉回路

必要性显然

充分性:

由于所有节点都是偶数度节点,那么必然存在一个简单环,如果这个环就是欧拉回路结论已经成立,否则删掉该环上所有边,子图中的节点一定不存在奇数度节点

由于图的连通性,子图与该环必定有公共顶点,以公共顶点为起点在子图中寻找简单环递归做

又因为子图中的环与原图简单环有公共顶点,所以二者可以并在一起,最终形成欧拉回路

证明: 无向图(G)为连通图,有且仅有两个奇数度顶点,则图存在欧拉通路

必要性显然

充分性:

将两个奇数度顶点直接连边,图(G)中必定存在欧拉回路

有向图同理

定理

1.一个非平凡联通图是欧拉图当且仅当它每条边属于奇数个环

证明:几个环交接处的边的两个顶点的度数为环数+1

实现

判断图中存在欧拉路或欧拉回路后,只要选择正确的起点无脑递归,无路可走就回溯,回溯时记录路径


inline void dfs(int now)
{
	for(int i=l;i<=r;++i)
	{
		if(g[now][i])
		{
			--g[now][i];
			--g[i][now];
			dfs(i);
		}
	}
	ret[++sum]=now;
}

最后将路径倒序输出

while(sum) printf("%d
",ret[sum--]);

为什么一定要倒序输出不是直接输出?

考虑以下情况(无向图):

标准(dfs)很可能(1)之后进入(2),转了一圈之后发现无法返回,那么我们(dfs)树上的顺序很可能是:

(1、2、3、4、2、5、6、1)

但这很明显不是欧拉路的顺序

若我们用栈,在回溯时将节点入栈,先将(2、4、3、2、1)压入栈底

而后将(6、5、1)进栈

那么倒序输出的顺序就是(1、5、6、1、2、3、4、2)

也就是说在求欧拉通路时,死路一定要走的但不能放在最早走,而是一旦遇到通过栈在走完回路之后通过

原文地址:https://www.cnblogs.com/knife-rose/p/15081251.html