问题:详见http://hihocoder.com/problemset/problem/1041

有n个城市,城市编号为1-n,城市间有n-1条路(所以,城市路网是一棵树)。给定一个序列S,要求判断是否存在一条路径,使得

  • 从城市 1 开始出发,每条路都需通过2次,最后回到1
  • 对于S中的城市,访问的顺序要从前到后。因为每条路可以走两次,所以这里要求的是第一次经过的顺序

思路:DFS

1. 预处理:找出所有结点的可达结点。

通过这个,我们就可以快速判断某个结点是否在某个子树中。比如下一个的访问目标为3,当前的位置是1,那么通过判断3是否在1的某个子树中,可以直接决定下一步应该选择哪个结点。

2. 从结点1开始深搜。直到按序访问到序列S中的每个点

  1. #include <iostream>
  2. #include <bitset>
  3. #include <string>
  4.  
  5. using namespace std;
  6. #define maxCity 100
  7. bitset<maxCity> roads[maxCity];//标识两个城市之间有路
  8. bitset<maxCity> reach[maxCity];//标识一个点的子节点,也就是到哪些点是可达的
  9.  
  10. void setReach(int curr, int father, int cityCnt){
  11. reach[curr][curr] = ;//自己到自己是可达的
  12. for (int son = ; son <= cityCnt; son++){
  13. if (father == son)
  14. continue;
  15. if (roads[curr][son]){//如果father 和 son 之间是有路的
  16. setReach(son, curr, cityCnt);//计算son的可达点
  17. reach[curr] |= reach[son];//通过 或 操作,把son的可达点加入到curr的可达集合中
  18. }
  19. }
  20. }
  21. //当前访问到的城市 currID
  22. //下一个应该访问在要求序列中的第 rIndex 个城市
  23. //要求的序列包含 rCnt 个城市
  24. int rIndex = ;
  25. bool flag = false;//是否找到满足条件的路径
  26. void dfs(int currID, int father, int rCnt, int* rCity, int cityCnt){
  27. if (currID == rCity[rIndex])//当前要访问的正好是序列中的下一个城市
  28. ++rIndex;
  29. if (rIndex == rCnt){//序列的要求已经满足
  30. flag = true;
  31. return;
  32. }
  33. while (rIndex < rCnt){//判断从当前点继续是否能走完整个要求的序列
  34. int i = ;
  35. for (; i <= cityCnt; i++){
  36. if (i == currID || i == father)
  37. continue;
  38. //遍历currID的所有子节点,每个节点代表了一棵子树
  39. //roads[currID][i] 不为0, 表明currID和i有路
  40. //reach[i][rCity[rIndex]] 不为0,表明从i可以直到要求序列的下一个城市
  41. //同时满足条件,也就是说currID的下一个可以访问i,然后通过 i 走到下一个要求的城市
  42. if (roads[currID][i] && reach[i][rCity[rIndex]]){
  43. roads[currID][i] = ;
  44. dfs(i, currID, rCnt, rCity, cityCnt);//访问 i 这棵子树
  45. break;//每个节点只能属于一棵子树,所以其它的就不用再判断。已经知道下一个要求的节点在 i 的子树中,所以不需要再去判断其它节点的子树
  46. }
  47. }
  48. if (i > cityCnt)//没有在currID中的任何一个子树中找到下一个要求的结点
  49. break;
  50. }
  51. }
  52. int main(){
  53. int cnt, cityCnt, rCnt, *rCity;
  54. cin >> cnt;
  55.  
  56. while (cnt-- > ){
  57. flag = false;
  58. cin >> cityCnt;
  59. rIndex = ;
  60. //初始化,城市间都没有路,都没有子节点
  61. for (int i = ; i <= cityCnt; i++){
  62. roads[i].reset();
  63. reach[i].reset();
  64. }
  65. for (int i = ; i < cityCnt - ; i++){
  66. int a, b;
  67. //a, b间有路
  68. cin >> a >> b;
  69. roads[a][b] = ;
  70. roads[b][a] = ;
  71. }
  72. cin >> rCnt;
  73. rCity = new int[rCnt];
  74. for (int i = ; i < rCnt; i++)
  75. cin >> rCity[i];
  76. setReach(, -, cityCnt);
  77. dfs(, -, rCnt, rCity, cityCnt);
  78. if (flag)
  79. cout << "YES" << endl;
  80. else
  81. cout << "NO" << endl;
  82. }
  83. return ;
  84. }

注:

1. bitset 需要#include <bitset>

bitset<maxCity> roads[maxCity]   声明了一个数组,数组的元素类型为bitset<maxCity>,每一个数用maxCity位的二进制来表示

2. 在计算每个点可达的集合,以及寻找路径的时候都有一个判断条件:判断当前点的son是否和父节点father一样

如果不进行这个判断,假设树的结构为 1-2,也就是只有两个城市1、2,它们中间有一条路。以setReach为例,递归的过程如下:

setReach(1, -1)->(因为1可以到达2)setReach(2, 1)->(从城市1开始判断,2可以到达1)setReach(1, 2)->setReach(2,1)...死循环

这里只需要考虑当前点的父结点,而不用继续向上考虑,是因为当前点和父结点的上层并不会有路径

【hihoCoder】1041. 国庆出游的更多相关文章

  1. hihoCoder 1041 国庆出游 最详细的解题报告

    题目来源:国庆出游 解题思路(下面是大神的写的): 把题目中的序列称作S,树称作T.那么对于S中的任意节点x,x的子孙节点如果在S出现的话,那么这个子孙节点的位置是有一定要求的:x的所有子孙节点在S中 ...

  2. hihoCoder 1041 国庆出游 (DFS)

    题意: 小Hi和小Ho准备国庆期间去A国旅游.A国的城际交通比较有特色:它共有n座城市(编号1-n):城市之间恰好有n-1条公路相连,形成一个树形公路网.小Hi计划从A国首都(1号城市)出发,自驾遍历 ...

  3. hihocoder——1041国庆出游(搜索)

    描述 小Hi和小Ho准备国庆期间去A国旅游.A国的城际交通比较有特色:它共有n座城市(编号1-n):城市之间恰好有n-1条公路相连,形成一个树形公路网.小Hi计划从A国首都(1号城市)出发,自驾遍历所 ...

  4. hiboCoder 1041 国庆出游 dfs+思维

    先抽象出一棵以1做为根结点的树.给定了访问序列a[1..m]. 考虑两种特殊情况: 1.访问了某个a[j],但是存在a[i]没有访问且i < j,出现这种情况说明a[j]一定是a[i]的祖先节点 ...

  5. Hiho1041 国庆出游 搜索题解

    题目3 : 国庆出游 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描写叙述 小Hi和小Ho准备国庆期间去A国旅游.A国的城际交通比較有特色:它共同拥有n座城市(编号1-n): ...

  6. 国庆出游神器:魔幻黑科技换天造物,让vlog秒变科幻大片!

    摘要:国庆旅游景点人太多,拍出来的照片全是人人人.车车车,该怎么办?不妨试试这个黑科技,让你的出游vlog秒变科幻大片. 本文分享自华为云社区<国庆出游神器,魔幻黑科技换天造物,让vlog秒变科 ...

  7. [HIHO1041]国庆出游(DFS, bitset)

    题目链接:http://hihocoder.com/problemset/problem/1041 学会了用C++的bitset哈,可喜可贺.以后遇到超过64位想用位来表示状态就不愁了哈. 这题用bi ...

  8. HihoCoder1041 国庆出游 树形DP第四题

    小Hi和小Ho准备国庆期间去A国旅游.A国的城际交通比较有特色:它共有n座城市(编号1-n):城市之间恰好有n-1条公路相连,形成一个树形公路网.小Hi计划从A国首都(1号城市)出发,自驾遍历所有城市 ...

  9. hiho_1041 国庆出游

    题目 给定一棵树,N个节点,N - 1条边.给定m个节点,能否找出一种遍历方法,使得首次到达节点ai的时间小于首次到达节点aj的时间(i < j).且经过的路径上的每条边都最多走两遍 分析 我的 ...

随机推荐

  1. [unity3d插件]2dtoolkit系列一 创建精灵

    从今天开始要做一个2d游戏,由于之前都是做cocos2dx的,然后接触了一段时间的unity3d,都是做3D方面的东西,得知要做2d游戏还是有点开心的,或许因为不想丢失之前的2d游戏的一些思想,然后接 ...

  2. 并发异步处理队列 .NET 4.5+

    namespace Test { using System; using System.Threading; using System.Threading.Tasks; using Microshao ...

  3. tnsnames.ora 监听配置文件详解

    今天是重要的一天.将XML数据导入ORACLE遇到很多问题,学了好多,其中很长时间花在网络配置上,刚开始学,具体原因不知道,先把搜集到的好文章存下来,以后慢慢研究. 监听配置文件            ...

  4. Java学习笔记(一)——HelloWorld

    一.安装JDK 1.下载链接: http://www.oracle.com/technetwork/java/javase/downloads/index.html 2.直接安装,不能有中文路径 3. ...

  5. ontouchstart

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta cont ...

  6. android 获取文件夹、文件的大小 以B、KB、MB、GB 为单位

    android 获取文件夹.文件的大小 以B.KB.MB.GB 为单位   public class FileSizeUtil { public static final int SIZETYPE_B ...

  7. 《DSP using MATLAB》示例Example5.1

    终于看到第5章了,继续努力,加油!!! 代码: xn = [0, 1, 2, 3]; N =4; Xk = dfs(xn,N) 用到的dfs函数: function [Xk] = dfs(xn,N) ...

  8. Ubuntu mysql

    To install mysql database in the ubuntu:    1. sudo apt-get install mysql-server 2. apt-get isntall ...

  9. [自动运维]ant脚本打包,上传文件到指定服务器,并部署

    1.根节点使用,表示根目录为当前目录,默认启动的target为build,项目名称为othersysm, <project basedir="." default=" ...

  10. js 的一点用法

     js 中的json对象,ajax返回数据dataType为json否则无法将数据转换成json对象 也就无法通过json字符串转换成对象object,那么他将始终是个字符串,也就无法进行 对象操作. ...