• 【hihoCoder】1041. 国庆出游


    问题详见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] = 1;//自己到自己是可达的
    12     for (int son = 1; 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 = 0;
    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 = 1;
    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] = 0;
    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-- > 0){
    57         flag = false;
    58         cin >> cityCnt;
    59         rIndex = 0;
    60         //初始化,城市间都没有路,都没有子节点
    61         for (int i = 0; i <= cityCnt; i++){
    62             roads[i].reset();
    63             reach[i].reset();
    64         }
    65         for (int i = 0; i < cityCnt - 1; i++){
    66             int a, b;
    67             //a, b间有路
    68             cin >> a >> b;
    69             roads[a][b] = 1;
    70             roads[b][a] = 1;
    71         }
    72         cin >> rCnt;
    73         rCity = new int[rCnt];
    74         for (int i = 0; i < rCnt; i++)
    75             cin >> rCity[i];
    76         setReach(1, -1, cityCnt);
    77         dfs(1, -1, rCnt, rCity, cityCnt);
    78         if (flag)
    79             cout << "YES" << endl;
    80         else
    81             cout << "NO" << endl;
    82     }
    83     return 0;
    84 }
    View Code

    注:

    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)...死循环

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

  • 相关阅读:
    Django中MySQL读写分离技术
    BBS+Blog项目开发
    数据算法 --hadoop/spark数据处理技巧 --(5.移动平均 6. 数据挖掘之购物篮分析MBA)
    数据算法 --hadoop/spark数据处理技巧 --(3.左外连接 4.反转排序)
    数据算法 --hadoop/spark数据处理技巧 --(1.二次排序问题 2. TopN问题)
    mysql ---- Host '' is not allowed to connect to this MySQL server
    win 8.0.12
    Transformer 和 Transformer-XL——从基础框架理解BERT与XLNet
    Transformer 详解
    XLNet:运行机制及和Bert的异同比较
  • 原文地址:https://www.cnblogs.com/coolqiyu/p/5372572.html
Copyright © 2020-2023  润新知