「图论」欧拉路

定义

通路:一条从\(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\n",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\)

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

posted @ 2021-07-30 20:25  lovelyred  阅读(437)  评论(0编辑  收藏  举报