[hihoCoder] 第五十周: 欧拉路·二
描述
在上一回中小Hi和小Ho控制着主角收集了分散在各个木桥上的道具,这些道具其实是一块一块骨牌。
主角继续往前走,面前出现了一座石桥,石桥的尽头有一道火焰墙,似乎无法通过。
小Hi注意到在桥头有一张小纸片,于是控制主角捡起了这张纸片,只见上面写着:
将M块骨牌首尾相连放置于石桥的凹糟中,即可关闭火焰墙。切记骨牌需要数字相同才能连接。
——By 无名的冒险者
小Hi和小Ho打开了主角的道具栏,发现主角恰好拥有M快骨牌。
小Ho:也就是说要把所有骨牌都放在凹槽中才能关闭火焰墙,数字相同是什么意思?
小Hi:你看,每一块骨牌两端各有一个数字,大概是只有当数字相同时才可以相连放置,比如:
小Ho:原来如此,那么我们先看看能不能把所有的骨牌连接起来吧。
输入
第1行:2个正整数,N,M。分别表示骨牌上出现的最大数字和骨牌数量。1≤N≤1,000,1≤M≤5,000
第2..M+1行:每行2个整数,u,v。第i+1行表示第i块骨牌两端的数字(u,v),1≤u,v≤N
输出
第1行:m+1个数字,表示骨牌首尾相连后的数字
比如骨牌连接的状态为(1,5)(5,3)(3,2)(2,4)(4,3),则输出"1 5 3 2 4 3"
你可以输出任意一组合法的解。
- 样例输入
-
5 5
3 5
3 2
4 2
3 4
5 1 - 样例输出
-
1 5 3 4 2 3
小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-5
L2: 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-1
L2: 2-3-7-2
L3: 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)
End
PathSize ← PathSize + 1
Path[ PathSize ] ← u
小Ho:这代码好简单,我觉得我可以实现它!
小Hi:那么实现就交给你了
小Ho:没问题!交给我吧
#include <bits/stdc++.h>
using namespace std; int N, M;
int u, v;
vector<vector<int>> graph;
vector<int> inDegree;
vector<int> path; void dfs(int u) {
for (int v = ; v <= N; ++v) {
if (graph[v][u] == ) continue;
--graph[v][u];
--graph[u][v];
dfs(v);
}
path.push_back(u);
} int main() {
while (cin >> N >> M) {
graph.assign(N + , vector<int>(N + , ));
inDegree.assign(N + , );
path.clear();
for (int i = ; i < M; ++i) {
cin >> u >> v;
++graph[u][v];
++graph[v][u];
++inDegree[v];
++inDegree[u];
}
int start = ;
for (int i = ; i <= N; ++i) if (inDegree[i] & ) {
start = i;
break;
}
dfs(start);
for (int i = ; i < path.size(); ++i) {
cout << path[i] << " ";
}
cout << endl;
}
return ;
}
[hihoCoder] 第五十周: 欧拉路·二的更多相关文章
- hihocoder 1181 欧拉路.二
传送门:欧拉路·二 #1181 : 欧拉路·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在上一回中小Hi和小Ho控制着主角收集了分散在各个木桥上的道具,这些道具其 ...
- hiho欧拉路·二 --------- Fleury算法求欧拉路径
hiho欧拉路·二 分析: 小Ho:这种简单的谜题就交给我吧! 小Hi:真的没问题么? <10分钟过去> 小Ho:啊啊啊啊啊!搞不定啊!!!骨牌数量一多就乱了. 小Hi:哎,我就知道你会遇 ...
- [hihoCoder] 第四十九周: 欧拉路·一
题目1 : 欧拉路·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho最近在玩一个解密类的游戏,他们需要控制角色在一片原始丛林里面探险,收集道具,并找到最 ...
- hiho一下 第四十九周 欧拉路
http://hihocoder.com/contest/hiho49/problem/1 给定无孤立结点图G,若存在一条路,经过图中每边一次且仅一次,该条路称为欧拉路. 一个无向图存在欧拉路当且仅当 ...
- hihoCoder #1181: 欧拉路·二 (输出路径)
题意: 给定一个图,要求打印出任一条欧拉路径(保证图肯定有欧拉路). 思路: 深搜的过程中删除遍历过的边,并在回溯时打印出来.在深搜时会形成多个环路,每个环都有一个或多个结点与其他环相扣,这样就可以产 ...
- hiho一下 第四十九周 欧拉路·一
[题目链接]:click here~~ 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描写叙述 小Hi和小Ho近期在玩一个解密类的游戏.他们须要控制角色在一片原始丛林里面探险 ...
- hihocoder 第五十二周 高斯消元·二【高斯消元解异或方程 难点【模板】】
题目地址:http://hihocoder.com/contest/hiho57/problem/1 输入 第1..5行:1个长度为6的字符串,表示该行的格子状态,1表示该格子是亮着的,0表示该格子是 ...
- [hihoCoder] 第五十二周: 连通性·一
题目1 : 连通性·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 还记得上次小Hi和小Ho学校被黑客攻击的事情么,那一次攻击最后造成了学校网络数据的丢失.为了避免再 ...
- 【HIHOCODER 1181】欧拉路·二
描述 在上一回中小Hi和小Ho控制着主角收集了分散在各个木桥上的道具,这些道具其实是一块一块骨牌. 主角继续往前走,面前出现了一座石桥,石桥的尽头有一道火焰墙,似乎无法通过. 小Hi注意到在桥头有一张 ...
随机推荐
- Android学习笔记六:六大布局
六大界面布局方式包括: 线性布局(LinearLayout).帧布局(FrameLayout).表格布局(TableLayout).相对布局(RelativeLayout).绝对布局(Absolute ...
- ES6学习笔记十:模块的导入、导出
一:模块导入 1) import { 要导入的属性.方法民 } from '模块路径'; 2)该种方法需要有配置文件,指明模块所在路径 import { 要导入的属性.方法民 } from '模块名' ...
- EF Code First导航属性一对一关系中注意点及配置方法
//学生 public class Student { [key] public int StId { get; set; } public int SocialSecurityNumber { ge ...
- 单链表Java实现
近期在复习基本数据结构,本文是单链表的Java实现,包含对单链表的实现插入删除查找遍历等.最后还实现了单链表的逆置. 实现了多项式相加,多项式相乘. 原文章及完整源码在这里 http://binhua ...
- mysql在字符串中查找模式
查看以电话号码138开头的电话 select id, phone from user where phone like '138%'
- 有效利用番茄工作法提高效率--XorTime的使用方法
之前下载过番茄工作法XorTime,但是一直不知道怎么用,我想很多朋友应该也会遇到这种情况,于是我通过网上查找并直接总结,把XorTime的使用方法给写下,希望能够帮到更多的朋友.. ...
- C#代码实现邮箱验证C#中及一些常用的正则表达式
.验证用户名和密码:("^[a-zA-Z]\w{5,15}$")正确格式:"[A-Z][a-z]_[0-9]"组成,并且第一个字必须为字母6~16位: .验证电 ...
- fileUpload(草稿)
Java关于文件上传的一个例子 发表于2012/6/7 13:01:56 1374人阅读 分类: JavaWeb 文件上传不能用get方式提交,因为他提交的数据量最多只有1kb, IE浏览器默认情况 ...
- (转)Groupon前传:从10个月的失败作品修改,1个月找到成功 并不挶泥在这个点子上面,它反而往后站一步,看看他们已经做好的这个网站,可以再怎么包装成另一个完完全全不同的网站?所有的人所做的每件失败的事情中, 一定有碰到或含有成功的答案」在里面,只是他们不知道而已。 人不怕失败」,只怕宣布失败」
(转)Groupon前传:从10个月的失败作品修改,1个月找到成功 今天读到 一个非常励志人心的故事 ,就像现在「叶问」有「前传」,最近很火红的团集购网站Groupon 也出现了「Groupon前传」 ...
- 微信公众平台HTTPS方式调用配置免费https服务器
微信公众平台数据传输安全,提高业务安全性,公众平台将不再支持HTTP方式调用.避免影响正常使用中含有HTTP方式调用的服务,请开发者尽快调整,将现有通过HTTP方式调用的切换成HTTPS调用,平台将于 ...