【图的dfs + bitset+ 套路】hihocoder. 1041
来源:互联网 发布:php在线加密 编辑:程序博客网 时间:2024/05/17 09:20
http://hihocoder.com/problemset/problem/1041
每当我以为 dfs 我学得还可以了,就会发现自己其实对某些性质运用的并不是那么熟练
(向黑恶势力低头
其实 这题考点主要是图的dfs ,但是中间的某个步骤可以用bitset 优化一下;
题意:
给一颗树, 每条边 可以走两次,来回各一次。 给你一个遍历顺序,问是否能够按照顺序遍历。
比如:
7
1 2
1 3
2 4
2 5
3 6
3 7
如果按 3 7 2 遍历 可行, 但是按照 3 2 7 遍历则不可以,因为边只能走两次;
然后因为这题 n 比较小,所以可以强行暴力 硬A 过去。
这里讲一个O n 时间复杂度的方法,利用的就是dfs的性质
先说一个方法:
void dfs(int rot,int pre){ vis[rot][rot]=1; for(int i=head[rot];i!=-1;i=edge[i].next){ int v=edge[i].to; if(v==pre) continue; dfs(v,rot); for(int j=1;j<=n;j++){ vis[rot][j] |=vis[v][j]; } }}
看看这个小套路 利用dfs 小性质 来完成 某些点到某些点的子树。
但这里显然是int vis[N][N] 来完成的, 不但可能开不下,而且这里还是n*n 的复杂度,谈何On 呢
这里显然就要用到 bitset,
这里 插入学习一下bitset。
可以当作一个bool型数组考虑,
bitset< N> bs; 可以考虑成一个数组bool bs[N]。
相关操作:
bs.set(); 全部置1,bs.reset()全部置0;
bs.set(pos);等价于bs[pos]=1,bs.reset(pos)等价于bs[pos]=0;
最重点的来了,bitset< N> a, b;
a和b可以直接进行操作,
!a //按位取反
a^b //按位异或
a|b //按位或
a&b //按位与
a=b<<3 //整体移位
a.count(); //a中1的个数
所以上面那段代码
void dfs(int rot,int pre){ vis[rot][rot]=1; for(int i=head[rot];i!=-1;i=edge[i].next){ int v=edge[i].to; if(v==pre) continue; dfs(v,rot); vis[rot]|=vis[v]; //因为二进制运算 这里的时间复杂度 就是常数级别 }}
然后我们知道了这个
接下来的处理方式 就仁者见仁了。
我们可以这样
void dfs2(int rot,int pre){ if(flag) return; if(pos==m){ flag=1; return; } if(rot==f[pos]) pos++; // 走下个点 num[rot]++; // num这点走了一次 while(pos<=m){ int cnt=pos; for(int i=head[rot];i!=-1;i=edge[i].next){ int v=edge[i].to; if(v==pre || num[v]) continue; //若一条路一个方向只能走一次 if(vis[v][f[pos]]){ dfs2(v,rot); } } if(cnt==pos) break; }}
这个的精髓就在于利用的dfs 的回溯走了那一遍回来的路。
比如 3 7 2
1走到3 之后 又走到7 之后 回溯到1 又走到 2
327 的话 走完2之后 就走不了3 -7 ,因为3走过一遍。
#include<iostream>#include<stdio.h>#include<string.h>#include<math.h>#include<algorithm>#include<stdlib.h>#include<queue>#include<stack>#include<map>#include<vector>#include<bitset>#define mem(a) memset(a,0,sizeof(a))#define ll __int64#define INF 0x7fffffff //INT_MAX#define inf 0x3f3f3f3f //const double PI = acos(-1.0);const double e = exp(1.0);template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }using namespace std;/* * 学习一下bitset。可以当作一个bool型数组考虑,bitset<N> bs; 可以考虑成一个数组bool bs[N]。相关操作:bs.set(); 全部置1,bs.reset()全部置0;bs.set(pos);等价于bs[pos]=1,bs.reset(pos)等价于bs[pos]=0;最重点的来了,bitset<N> a, b;a和b可以直接进行操作,!a //按位取反a^b //按位异或a|b //按位或a&b //按位与a=b<<3 //整体移位a.count(); //a中1的个数*///int vis[105][105];bitset<105>vis[105];struct Edge{ int to; int next; int use;}edge[1000];int cnt;int head[1005];int n,m;void addedge(int u,int v){ edge[cnt].to=v; edge[cnt].use=0; edge[cnt].next=head[u]; head[u]=cnt++;}void dfs(int rot,int pre){ vis[rot][rot]=1; for(int i=head[rot];i!=-1;i=edge[i].next){ int v=edge[i].to; if(v==pre) continue; dfs(v,rot); vis[rot]|=vis[v]; }}int flag;int pos;int f[105];int num[105];void dfs2(int rot,int pre){ if(flag) return; if(pos==m){ flag=1; return; } if(rot==f[pos]) pos++; // 走下个点 num[rot]++; // num这点走了一次 while(pos<=m){ int cnt=pos; for(int i=head[rot];i!=-1;i=edge[i].next){ int v=edge[i].to; if(v==pre || num[v]) continue; //若一条路一个方向只能走一次 if(vis[v][f[pos]]){ dfs2(v,rot); } } if(cnt==pos) break; }}void init(){ for(int i=1;i<=n;i++) vis[i].reset(); memset(num,0,sizeof(num)); cnt=0; memset(head,-1,sizeof(head));}int main() { freopen("1.txt","r",stdin); int cas; scanf("%d",&cas); while(cas--){ init(); scanf("%d",&n); for(int i=1;i<n;i++){ int u,v; scanf("%d %d",&u,&v); addedge(u,v); addedge(v,u); } dfs(1,0); scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%d",&f[i]); } flag=0; pos=1; dfs2(1,-1); flag?printf("YES\n"):printf("NO\n"); } return 0;}
- 【图的dfs + bitset+ 套路】hihocoder. 1041
- hihoCoder--1041 国庆出游(dfs + bitset)
- hihoCoder 1041 : 国庆出游 (dfs+bitset 很不错的题!)
- hihocoder 1041 国庆出游 (DFS + bitset 好题)
- hihocoder #1041 : 国庆出游(DFS bitset保存子树集合用于指导DFS遍历过程)
- hihocoder 1041 国庆出游 dfs
- hihoCoder 1236 bitset + 分块
- Hihocoder 147周 小HI的烦恼 bitset(技巧)
- hihoCoder 1513: 小Hi的烦恼(五维偏序+bitset)
- Hihocoder 1236 Scores【分块+bitset】
- hihoCoder 1236 Scores(bitset+分块)
- HihoCoder-1236-Scores【bitset】【五维偏序】
- dfs套路步骤
- hihocoder #1041 : 国庆出游 (DFS)
- hihocoder 1513 小Hi的烦恼 五维数点求集合的交集 bitset用法
- hihocoder 第147周 小Hi的烦恼 (bitset的使用)
- hihoCoder : 题目1 : 小Hi的烦恼(bitset应用 TODO: 待优化 )
- hihoCoder #1054 dfs
- # **linux 某一目录下所有文件时间戳**
- linux C编程(五)函数指针与函数调用
- 电子商务模式都有哪些
- 深入浅出 RPC - 浅出篇
- 手机中的网路类型概念
- 【图的dfs + bitset+ 套路】hihocoder. 1041
- C语言程序代码优化
- 相对路径和绝对路径的区别
- 数据结构实验之求二叉树后序遍历和层次遍历
- [Lintcode]Clone Graph
- 深入浅出 RPC - 深入篇
- 关键字
- 用html实现企业邮箱登陆界面
- HTTP请求报文和HTTP响应报文