hiboCoder 1041 国庆出游 dfs+思维
先抽象出一棵以1做为根结点的树。给定了访问序列a[1..m]。
考虑两种特殊情况:
1.访问了某个a[j],但是存在a[i]没有访问且i < j,出现这种情况说明a[j]一定是a[i]的祖先节点,必须访问过a[j]才能访问a[i],这种情况是不符合条件的。
2.当某个点被访问后并且这个节点被回溯之后,它的子树中仍然存在序列中的节点没被访问,那么些节点不会有机会再被访问,不符合情况。
思路:根据访问序列中节点的下标,给定所有待访问节点一个权值,代表他们的访问顺序,例如数据:
7 1 2 1 3 2 4 2 5 3 6 3 7 3 3 2 7
这组数据中,分别给3 2 7 一个权值,w[3] = 0, w[2] = 1, w[7] = 2, 其他节点的权值都是inf,dp[i]表示以节点i作为根结点的子树中最小的权值,如果某个节点i下面存在权值比它小的节点j,说明满足第一种情况,肯定是不合理的。
当处理了第一种情况,并且得到了所有dp[i],那么现在要开始处理第二种情况。模拟深度优先遍历这棵树即可,在遍历的同时,一定是按照给定的访问序列来顺序访问,给一个全局变量f,代表当前需要访问的节点的权值,假设当前在i节点处,它的子节点是Vj,那么一定是优先访问dp[Vj] = f的节点,然后继续找,知道有节点u满足w[u] = f,说明找到了这个节点,让f++,该寻找下一个节点了,一直重复即可,注意每个节点只访问一次,当出现要访问某个被访问过的节点时,就说明符合第二种情况。其实这种方法也可以处理第一种情况,由于要预处理dp[i],所以我在建树的同时就把第一种情况处理了。最后判断序列中是否有没被访问过得节点,有则说明是满足第二种情况的。总的复杂度是O(n*logn)
贴一组我认为很容易WA的测试数据:
6
4
1 2
2 3
3 4
3
4 3 2
7
1 2
1 3
2 4
2 5
3 6
3 7
3
3 7 2
7
1 2
1 3
2 4
2 5
3 6
3 7
3
3 2 7
4
1 2
2 3
3 4
4
4 3 2 1
7
1 2
1 3
2 4
2 5
3 6
3 7
4
2 4 3 5
9
1 2
1 3
2 4
2 5
3 6
3 7
4 8
4 9
5
2 4 8 5 9
正确答案是:
NO
YES
NO
NO
NO
NO
AC代码:
#include <cstdio> #include <cmath> #include <cctype> #include <bitset> #include <algorithm> #include <cstring> #include <utility> #include <string> #include <iostream> #include <map> #include <set> #include <vector> #include <queue> #include <stack> using namespace std; #pragma comment(linker, "/STACK:1024000000,1024000000") #define eps 1e-10 #define inf 0x3f3f3f3f #define PI pair<int, int> typedef long long LL; const int maxn = 100 + 5; vector<int>G[maxn]; int vis[maxn], w[maxn], a[maxn], dp[maxn]; int n, m; bool build_tree(int u, int par) { if(G[u].size() == 1 && G[u][0] == par) { dp[u] = w[u]; return true; } int ans = inf; for(int i = 0; i < G[u].size(); ++i) { int v = G[u][i]; if(v == par) continue; if(!build_tree(v, u)) return false; if(w[u] != inf && w[u] > dp[v]) return false; ans = min(ans, dp[v]); } dp[u] = min(ans, w[u]); return true; } int f; void dfs(int u,int par) { vis[u]++; if(w[u] == f) f++; if(f >= m) return; for(int i = 0; i < G[u].size(); ++i) { int v = G[u][i]; if(v == par) continue; if(!vis[v] && dp[v] == f) { //未访问过f能在以v为根结点的子树中找到 dfs(v, u); } } } bool cmp(int a, int b) { return dp[a] < dp[b]; } bool solve(int n, int m) { //以第一个点为根建树 bool ok = build_tree(1, -1); if(!ok) return false; for(int i = 1; i <= n; ++i) { //排序,根据节点的权值确定访问顺序 sort(G[i].begin(), G[i].end(), cmp); } f = 0; dfs(1, -1); for(int i = 0; i < m; ++i) { if(!vis[a[i]]) return false; } return true; } int main() { int T; scanf("%d", &T); while(T--) { scanf("%d", &n); for(int i = 1; i <= n+1; ++i) G[i].clear(); int u, v; for(int i = 0; i < n-1; ++i) { scanf("%d%d", &u, &v); G[u].push_back(v); G[v].push_back(u); } memset(vis, 0, sizeof(vis)); for(int i = 1; i <= n; ++i) w[i] = inf; scanf("%d", &m); //赋予权值 for(int i = 0; i < m; ++i) { scanf("%d", &a[i]); w[a[i]] = i; } int ok = solve(n, m); if(ok) printf("YES\n"); else printf("NO\n"); } return 0; }
如有不当之处欢迎指出!
hiboCoder 1041 国庆出游 dfs+思维的更多相关文章
- hihoCoder 1041 国庆出游 (DFS)
题意: 小Hi和小Ho准备国庆期间去A国旅游.A国的城际交通比较有特色:它共有n座城市(编号1-n):城市之间恰好有n-1条公路相连,形成一个树形公路网.小Hi计划从A国首都(1号城市)出发,自驾遍历 ...
- hihoCoder 1041 国庆出游 最详细的解题报告
题目来源:国庆出游 解题思路(下面是大神的写的): 把题目中的序列称作S,树称作T.那么对于S中的任意节点x,x的子孙节点如果在S出现的话,那么这个子孙节点的位置是有一定要求的:x的所有子孙节点在S中 ...
- 【hihoCoder】1041. 国庆出游
问题:详见http://hihocoder.com/problemset/problem/1041 有n个城市,城市编号为1-n,城市间有n-1条路(所以,城市路网是一棵树).给定一个序列S,要求判断 ...
- hihocoder——1041国庆出游(搜索)
描述 小Hi和小Ho准备国庆期间去A国旅游.A国的城际交通比较有特色:它共有n座城市(编号1-n):城市之间恰好有n-1条公路相连,形成一个树形公路网.小Hi计划从A国首都(1号城市)出发,自驾遍历所 ...
- 【hiho1041】国庆出游 dfs+bitset
题目大意:给定一棵 N 个节点的有根树,1 号节点为根节点,现遍历整棵树,要求每条边仅被经过两次,问是否存在一种特定的遍历方式使得 dfs 序中节点的相对前后关系符合给定的顺序. 题解: 首先,由于要 ...
- hdu6035[dfs+思维] 2017多校1
/*hdu6035[dfs+思维] 2017多校1*/ //合并色块, 妙啊妙啊 #include<bits/stdc++.h> using namespace std; ; const ...
- Hiho1041 国庆出游 搜索题解
题目3 : 国庆出游 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描写叙述 小Hi和小Ho准备国庆期间去A国旅游.A国的城际交通比較有特色:它共同拥有n座城市(编号1-n): ...
- D. Eternal Victory(dfs + 思维)
D. Eternal Victory time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- 国庆出游神器:魔幻黑科技换天造物,让vlog秒变科幻大片!
摘要:国庆旅游景点人太多,拍出来的照片全是人人人.车车车,该怎么办?不妨试试这个黑科技,让你的出游vlog秒变科幻大片. 本文分享自华为云社区<国庆出游神器,魔幻黑科技换天造物,让vlog秒变科 ...
随机推荐
- Java常用类--数字常用类
math java提供了基本的 + - * / %等基本算术运算的运算符,但对于更复杂的数学运算比如:三角函数,对数运算,指数运算就无能为力了.Java提供了Math工具类来完成这些复杂的运算,Mat ...
- Hibernate (四)
1 懒加载 (感觉用处不是很大) 需要的时候加载,不需要的时候就不加载. 1.1 环境的搭建 hibernate.cfg.xml <?xml version='1.0' encoding='ut ...
- echo 0000
一个奇怪的问题,正常状态下如果sql插入失败,则输出0000,代码如下: $stmt=$db->prepare("insert into message(user,title,cont ...
- 珍爱生命,远离JS=>JS避坑记
JavaScript避坑记 转载请注明源地址: http://www.cnblogs.com/funnyzpc/p/8407952.html 上图=> 有意思的漫画,不知大家看懂了没,这里我想说 ...
- Git Batch命令(转)
echo 和 @ 回显命令 @ #关闭单行回显 echo off #从下一行开始关闭回显 @echo off #从本行开始关闭回显.一般批处理第一行都是这个 echo on #从下一行开始打开回显 e ...
- JAVA设计模式---模板方法
1.定义: 在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤. (为了防止子类改变模板方法中的算法,可以将模板方法声明为 ...
- SpringMVC源码情操陶冶-AbstractUrlHandlerMapping
承接前文SpringMVC源码情操陶冶-AbstractHandlerMapping,前文主要讲解了如何获取handler处理对象,本文将针对beanName注册为handler对象作下解析 Abst ...
- ZOJ1450 BZOJ1136 BZOJ1137 HDU3932[最小圆覆盖]
Minimal Circle Time Limit: 5 Seconds Memory Limit: 32768 KB You are to write a program to find ...
- Redis集群分布
Redis系列 作者Mr.Chen,转载请注明博客出处:http://www.cnblogs.com/cjh-notes/ Redis集群存储 先看下架构图,下面说明其存储原理:首先redis每个节点 ...
- phpMyAdmin的使用
phpMyAdmin的使用 安装MySQL数据库后,用户即可在命令行提示符下进行创建数据库和数据表等各种操作,但这种方法非常麻烦,而且需要有专业的SQL语言知识.PHP官方开发了一个类似于SQL Se ...