DSAA之图论Euler Circuits问题(九)

1. 从实际演变的问题

A popular puzzle is to reconstruct these figures using a pen, drawing each line exactly once. The pen may not be lifted from the paper while the drawing is being performed. As an extra challenge, make the pen finish at the same point at which it started.

这里写图片描述

实际上是两个问题,**欧拉环游:**遍历每个边且起点和终点不重合,**欧拉回环:**遍历每个边且起点和终点重合。然后可以自己动笔试试上面三个图在两种问题下的解的情况。

1. 转化成图论

We can convert this problem to a graph theory problem by assigning a vertex to each intersection. Then the edges can be assigned in the natural manner.

图论的转化相当简单(概念上),针对欧拉回路一个充分必要条件为无向图必须是连通的且每个节点的度为偶数

The first observation that can be made is that an Euler circuit, which must end on its starting vertex, is possible only if the graph is connected and each vertex has an even degree (number of edges).

针对欧拉环游这个充分必要条件为无向图必须是连通的且有0或者2个节点的度为奇数。DSAA本节聚焦欧拉回路,如果一个问题是让我们测试欧拉回路是否存在,并且找出来该回路,那么下面提出的方案能够在线性时间解决这个问题。

2. 一种线性解决思路

  • Then the basic algorithm is to perform a depth-first search.
  • The main problem is that we might visit a portion of the graph and return to thestarting point prematurely.
    • If all the edges coming out of the start vertex have been used up, then part of the graph is untraversed. The easiest way to fix this is to find the first vertex on this path that has an untraversed edge, and perform another depth-first search. This will give another circuit, which can be spliced into the original. This is continued until all edges have been traversed.

上面三点是递进关系,使用DFS遍历无向有环图时,先不考虑具体实现上的问题,最先要解决就是过早的回环,而解决这个问题的方法就是从已经得到的遍历结果中,从左到右找到第一个具有没有访问过的边的节点,并以该节点再次进行一次DFS。
  DSAA这里给出了一个例子,如果抽象该例子来表示这一情况如下:第一次遍历的结果为 x 1 , x 2 , x 3 , x 1 x_{1},x_{2},x_{3},x_{1} x1,x2,x3,x1,然后假设 x 2 x_{2} x2是第一个具有未访问过的边的节点,以 x 2 x_{2} x2为起点再次进行深搜,得到的结果为 x 2 , x 4 , x 5 , x 2 x_{2},x_{4},x_{5},x_{2} x2,x4,x5,x2。然后将该序列加在原来的遍历序列中为 x 1 , x 2 , x 4 , x 5 , x 2 , x 3 , x 1 x_{1},x_{2},x_{4},x_{5},x_{2},x_{3},x_{1} x1,x2,x4,x5,x2,x3,x1,很显然得到的新序列是满足每个边只能访问一次的性质的。
  持续这一过程直到所有的边都被访问,最终得到的序列就是最终的答案。

3. 具体实现的思考

将访问过的边标记下,避免下一次继续访问(在邻接表的每一个链表使用一个指针指向最后一次访问过的边)。为了使splice简单,使用链表组织访问过的路径(因为插入和删除的时间复杂度为 O ( 1 ) O(1) O(1)),

  • To make splicing simple, the path should be maintained as a linked list.
  • To avoid repetitious scanning of adjacency lists, we must maintain, for each adjacency list, a pointer to the last edge scanned.
  • When a path is spliced in, the search for a new vertex from which to perform the next dfs must begin at the start of the splice point. This guarantees that the total work performed on the vertex search phase is O ( ∣ E ∣ ) O(|E|) O(E) during the entire life of the algorithm. With the appropriate data structures, the running time of the algorithm is O ( ∣ E ∣ + ∣ V ∣ ) O(|E| + |V|) O(E+V).

第二点这么做还有一个好处就是方便进行下一次的DFS搜索,总的算法复杂度在理论因为遍历所有的边(一些节点可能访问多次),所以为 O ( ∣ E ∣ + k ∣ V ∣ ) O(|E|+k|V|) O(E+kV),使用一些方法可以将常数k变成1,得到时间复杂度为 ( ∣ E ∣ + ∣ V ∣ ) (|E|+|V|) (E+V)

4. 总结

本篇就是按照DSAA的编排初步了解下欧拉回路和欧拉环游问题的若干问题,具体实现上会有更多值得探讨的问题,比如:进行下一次的DFS搜索时,发现无法回到当前DFS的出发点。
  最后从图论开始,DSAA就不是算法学习的最佳选择了。但是作为提前了解经典算法的教材来说,还是不错的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值