【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中的每个点
#include <iostream>
#include <bitset>
#include <string> using namespace std;
#define maxCity 100
bitset<maxCity> roads[maxCity];//标识两个城市之间有路
bitset<maxCity> reach[maxCity];//标识一个点的子节点,也就是到哪些点是可达的 void setReach(int curr, int father, int cityCnt){
reach[curr][curr] = ;//自己到自己是可达的
for (int son = ; son <= cityCnt; son++){
if (father == son)
continue;
if (roads[curr][son]){//如果father 和 son 之间是有路的
setReach(son, curr, cityCnt);//计算son的可达点
reach[curr] |= reach[son];//通过 或 操作,把son的可达点加入到curr的可达集合中
}
}
}
//当前访问到的城市 currID
//下一个应该访问在要求序列中的第 rIndex 个城市
//要求的序列包含 rCnt 个城市
int rIndex = ;
bool flag = false;//是否找到满足条件的路径
void dfs(int currID, int father, int rCnt, int* rCity, int cityCnt){
if (currID == rCity[rIndex])//当前要访问的正好是序列中的下一个城市
++rIndex;
if (rIndex == rCnt){//序列的要求已经满足
flag = true;
return;
}
while (rIndex < rCnt){//判断从当前点继续是否能走完整个要求的序列
int i = ;
for (; i <= cityCnt; i++){
if (i == currID || i == father)
continue;
//遍历currID的所有子节点,每个节点代表了一棵子树
//roads[currID][i] 不为0, 表明currID和i有路
//reach[i][rCity[rIndex]] 不为0,表明从i可以直到要求序列的下一个城市
//同时满足条件,也就是说currID的下一个可以访问i,然后通过 i 走到下一个要求的城市
if (roads[currID][i] && reach[i][rCity[rIndex]]){
roads[currID][i] = ;
dfs(i, currID, rCnt, rCity, cityCnt);//访问 i 这棵子树
break;//每个节点只能属于一棵子树,所以其它的就不用再判断。已经知道下一个要求的节点在 i 的子树中,所以不需要再去判断其它节点的子树
}
}
if (i > cityCnt)//没有在currID中的任何一个子树中找到下一个要求的结点
break;
}
}
int main(){
int cnt, cityCnt, rCnt, *rCity;
cin >> cnt; while (cnt-- > ){
flag = false;
cin >> cityCnt;
rIndex = ;
//初始化,城市间都没有路,都没有子节点
for (int i = ; i <= cityCnt; i++){
roads[i].reset();
reach[i].reset();
}
for (int i = ; i < cityCnt - ; i++){
int a, b;
//a, b间有路
cin >> a >> b;
roads[a][b] = ;
roads[b][a] = ;
}
cin >> rCnt;
rCity = new int[rCnt];
for (int i = ; i < rCnt; i++)
cin >> rCity[i];
setReach(, -, cityCnt);
dfs(, -, rCnt, rCity, cityCnt);
if (flag)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
return ;
}
注:
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. 国庆出游的更多相关文章
- hihoCoder 1041 国庆出游 最详细的解题报告
题目来源:国庆出游 解题思路(下面是大神的写的): 把题目中的序列称作S,树称作T.那么对于S中的任意节点x,x的子孙节点如果在S出现的话,那么这个子孙节点的位置是有一定要求的:x的所有子孙节点在S中 ...
- hihoCoder 1041 国庆出游 (DFS)
题意: 小Hi和小Ho准备国庆期间去A国旅游.A国的城际交通比较有特色:它共有n座城市(编号1-n):城市之间恰好有n-1条公路相连,形成一个树形公路网.小Hi计划从A国首都(1号城市)出发,自驾遍历 ...
- hihocoder——1041国庆出游(搜索)
描述 小Hi和小Ho准备国庆期间去A国旅游.A国的城际交通比较有特色:它共有n座城市(编号1-n):城市之间恰好有n-1条公路相连,形成一个树形公路网.小Hi计划从A国首都(1号城市)出发,自驾遍历所 ...
- hiboCoder 1041 国庆出游 dfs+思维
先抽象出一棵以1做为根结点的树.给定了访问序列a[1..m]. 考虑两种特殊情况: 1.访问了某个a[j],但是存在a[i]没有访问且i < j,出现这种情况说明a[j]一定是a[i]的祖先节点 ...
- Hiho1041 国庆出游 搜索题解
题目3 : 国庆出游 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描写叙述 小Hi和小Ho准备国庆期间去A国旅游.A国的城际交通比較有特色:它共同拥有n座城市(编号1-n): ...
- 国庆出游神器:魔幻黑科技换天造物,让vlog秒变科幻大片!
摘要:国庆旅游景点人太多,拍出来的照片全是人人人.车车车,该怎么办?不妨试试这个黑科技,让你的出游vlog秒变科幻大片. 本文分享自华为云社区<国庆出游神器,魔幻黑科技换天造物,让vlog秒变科 ...
- [HIHO1041]国庆出游(DFS, bitset)
题目链接:http://hihocoder.com/problemset/problem/1041 学会了用C++的bitset哈,可喜可贺.以后遇到超过64位想用位来表示状态就不愁了哈. 这题用bi ...
- HihoCoder1041 国庆出游 树形DP第四题
小Hi和小Ho准备国庆期间去A国旅游.A国的城际交通比较有特色:它共有n座城市(编号1-n):城市之间恰好有n-1条公路相连,形成一个树形公路网.小Hi计划从A国首都(1号城市)出发,自驾遍历所有城市 ...
- hiho_1041 国庆出游
题目 给定一棵树,N个节点,N - 1条边.给定m个节点,能否找出一种遍历方法,使得首次到达节点ai的时间小于首次到达节点aj的时间(i < j).且经过的路径上的每条边都最多走两遍 分析 我的 ...
随机推荐
- 提升 LaTeX 效率的小工具:Detexify LaTeX handwritten symbol recognition
Detexify LaTeX handwritten symbol recognition 用 LaTeX 的人找符号的表示方法通常很费事,需要去翻长长的列表.Detexify 是一个省事的小网站,只 ...
- Java学习随笔4:Java的IO操作
1. IO流的作用是读写设备上的数据,如硬盘文件.内存.键盘.网络等.根据数据走向,可分为:输入流和输出流:根据处理的数据类型,可分为:字节流和字符流.字节流可以处理所有类型的数据,如MP3.图片.视 ...
- HTML的格式、内容容器、表格标签
HTML(Hyper Text Markup Language,超文本标记语言)超指的是超链接. <html> --开始标签 <head> 网页上的控制信息 <ti ...
- sql 数字转人民币大写函数(两种方法)
,)) returns @rmb table( 亿 ) ,仟万 ) ,佰万 ) ,拾万 ) ,万 ) ,仟 ) ,佰 ) ,拾 ) ,元 ) ,角 ) ,分 )) as begin insert in ...
- 用DOM4J解析XML文件案例
用DOM4J解析XML文件案例,由于DOM4J不像JAXP属于JAVASE里,所以如果要使用DOM4J,则必须额外引入jar包,如图:
- JAVA 加减乘除
package homework; import javax.swing.JOptionPane; public class suanshu { public static void main(Str ...
- 分享Kali Linux 2016.2第48周虚拟机
分享Kali Linux 2016.2第48周虚拟机该虚拟机使用Kali Linux 2016.2第48周的64位镜像安装而成.基本配置如下:(1)该系统默认设置单CPU双核,内存为2GB,硬盘为50 ...
- Xamarin基础命名空间Microsoft.SqlServer.Server
Xamarin基础命名空间Microsoft.SqlServer.Server 该命名空间包含大量的类.接口和枚举,用于操作微软SQL Server数据库.该空间支持Xamarin.iOS和Xam ...
- js-错误处理与调试,JSON
错误处理与调试: 1.try-catch try{ window.someNoneXistentFunction(); }catch(error){ alert(error.message) } 2. ...
- 使用dSYM分析App崩溃日志
前言 我们在开发App过程中,因为连接到控制台,所以遇到问题会很容易找到问题代码.但是对于线上的App出现Crash的时候,我们不可能通过这种方式,也不现实,所以我们只能通过收集Crash信息,来解决 ...