hihocoder 1181(浅谈佛罗莱算法在求欧拉路径可行解中的应用)
来源:互联网 发布:java编程实战案例 编辑:程序博客网 时间:2024/06/05 10:03
传送门
小Ho:这种简单的谜题就交给我吧!
小Hi:真的没问题么?
<10分钟过去>
小Ho:啊啊啊啊啊!搞不定啊!!!骨牌数量一多就乱了。
小Hi:哎,我就知道你会遇到问题。
小Ho:小Hi快来帮帮我!
小Hi:好了,好了。让我们一起来解决这个问题。
<小Hi思考了一下>
小Hi:原来是这样。。。小Ho你仔细观察这个例子:
因为相连的两个数字总是相同的,不妨我们只写一次,那么这个例子可以写成:3-2-4-3-5-1。6个数字刚好有5个间隙,每个间隙两边的数字由恰好对应了一块骨牌。
如果我们将每一个数字看作一个点,每一块骨牌看作一条边。你觉得是怎么样的呢?
小Ho:以这个例子来说的话,就是:
要把所有的骨牌连起来,也就是把所有的边都走一次。咦,这不是欧拉路问题么!
小Hi:没错,这问题其实就是一个欧拉路的问题,不过和上一次不一样的在于,这一次我们要找出一条欧拉路径。
小Ho:那我们应该如何来找一条路径呢?
小Hi:我们还是借用一下上次的例子吧
使用我们上一次证明欧拉路判定的方法,我们在这个例子中找到了2条路径:
L1: 4-5-2-3-6-5L2: 2-4-1-2
假设我们栈S,记录我们每一次查找路径时的结点顺序。当我们找到L1时,栈S内的情况为:
S: 4 5 2 3 6 5 [Top]
此时我们一步一步出栈并将这些边删除。当我们到节点2时,我们发现节点2刚好是L1与L2的公共节点。并且L2满足走过其他边之后回到了节点2。如果我们在这个地方将L2先走一遍,再继续走L1不就刚好走过了所有边么。
而且在上一次的证明中我们知道,除了L1之外,其他的路径L2、L3...一定都满足起点与终点为同一个点。所以从任意一个公共节点出发一定有一条路径回到这个节点。
由此我们得到了一个算法:
在原图中找一个L1路径
从L1的终点往回回溯,依次将每个点出栈。并检查当前点是否还有其他没有经过的边。若存在则以当前点为起点,查找L2,并对L2的节点同样用栈记录重复该算法。
当L1中的点全部出栈后,算法结束。
在这里我们再来一个有3层的例子:
在这个例子中:
L1: 1-2-6-5-1L2: 2-3-7-2L3: 3-4-8-3
第一步时我们将L1压入栈S,同时我们用一个数组Path来记录我们出栈的顺序:
S: [1 2 6 5 1]Path:
然后出栈到节点2时我们发现了2有其他路径,于是我们把2的另一条路径加入:
S: 1 [2 3 7 2]Path: 1 5 6
此时L2已经走完,然后再开始弹出元素,直到我们发现3有其他路径,同样压入栈:
S: 1 2 [3 4 8 3]Path: 1 5 6 2 7
之后依次弹出剩下的元素:
S: Path: 1 5 6 2 7 3 8 4 3 2 1
此时的Path就正好是我们需要的欧拉路径。
小Ho:原来这样就能求出欧拉路,真是挺巧妙的。
小Hi:而且这个算法在实现时也有很巧妙的方法。因为DFS本身就是一个入栈出栈的过程,所以我们直接利用DFS的性质来实现栈,其伪代码如下:
DFS(u):While (u存在未被删除的边e(u,v))删除边e(u,v)DFS(v)EndPathSize ← PathSize + 1Path[ PathSize ] ← u
小Ho:这代码好简单,我觉得我可以实现它!
小Hi:那么实现就交给你了
小Ho:没问题!交给我吧
在图上dfs,每找到一条边就删除它然后继续搜,这样搜索到搜不下去的位置肯定是终点,搜的过程中用stack或者vector记录路径即可。
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<vector>using namespace std;const int MAXN=1002;int n,m,deg[MAXN],mp[MAXN][MAXN];vector<int > G[MAXN],path;inline void adde(int u,int v) {++deg[u],++deg[v];++mp[u][v],++mp[v][u];G[u].push_back(v),G[v].push_back(u);}void dfs(int p) {for (int i=0;i<G[p].size();++i) {int v=G[p][i];if (mp[p][v]) {--mp[p][v],--mp[v][p];dfs(v);}}path.push_back(p);}int main() {//freopen("hihocoder 1181.in","r",stdin);for (int i=1;i<=n;++i) G[i].clear();path.clear();memset(deg,0,sizeof(deg));memset(mp,0,sizeof(mp));scanf("%d%d",&n,&m);for (int i=0;i<m;++i) {int u,v;scanf("%d%d",&u,&v);adde(u,v);}int st=1;for (int i=1;i<=n;++i)if (deg[i]%2) {st=i;break;}dfs(st);for (int i=0;i<path.size();++i)printf("%d ",path[i]);puts("");return 0;}
- hihocoder 1181(浅谈佛罗莱算法在求欧拉路径可行解中的应用)
- HiHoCoder 1181 浅谈fleury算法求解无向图欧拉路径
- hihoCoder - 1181 - 欧拉路·二 (Fleury算法求欧拉路径)
- 关键路径在算法题中的应用
- Stereo Matching文献笔记之(六):浅谈置信度传播算法(Belief-Propagation)在立体匹配中的应用~
- Stereo Matching文献笔记之(六):浅谈置信度传播算法(Belief-Propagation)在立体匹配中的应用~
- hihoCoder - 1081 - 最短路径·一 (dijkstra算法!!)
- hihoCoder #1081 : 最短路径·一 (Dijkstra算法)
- 浅谈矩阵分解在推荐系统中的应用(转发)
- 深入A*算法----浅析A*算法在搜索最短路径中的应用
- 深入A*算法----浅析A*算法在搜索最短路径中的应用
- 浅谈Fleury(佛罗莱)算法 欧拉回路(及路径)
- 浅谈部分搜索+高效算法在搜索问题中的应用 by 楼天城
- 浅谈TeeChart组件在ASP中的应用
- 浅谈TeeChart组件在ASP中的应用
- 浅谈java在嵌入式开发中的应用
- 浅谈API函数在VB中的应用
- 浅谈TeeChart在Asp.Net中的应用
- JAXB控制CDATA节点转义
- HTML5视频直播技术介绍
- modify Framework
- 在监视器(Monitor)内部,是如何做到线程同步的
- python matplotlib 入门系列一:基本用法
- hihocoder 1181(浅谈佛罗莱算法在求欧拉路径可行解中的应用)
- 学习记录 9(17/10/12 于成都)
- c#中判断对象为空的几种方式(字符串等)
- Eclipse使用Maven创建工程时在quickstart那一步出错Could not resolve archetype ......
- var self = this
- 启动hadoop 2.6遇到的datanode启动不了
- struts2实现单文件上传
- Linear Regression(线性回归)
- 同济大学官网静态网页图