DFS序的学习
来源:互联网 发布:魔侠传 网络异常 编辑:程序博客网 时间:2024/06/03 18:45
//DFS序是个很有用的东西, 可以将树上的信息维护成一个连续的区间, 从而使树变成一条一条的链, 我们就可以用线段树来维护这些链, 从而求出我们所要的东西. 因为遍历的次序. 一个结点和其子树一定是在一个连续的区间内. 遍历的写法:
void dfs_id(int u,int fa){ p1[u] = ++ti; for(int i=head[u]; ~i ; i = s[i].next){ int to = s[i].to; if(fa == to) continue; dfs_id(to,u); } p2[u] = ti;} //p1存的是第一次遇到时序号,p2是第二次遇到的序号.//那么结点u及其子树存在的连续区间就是p1[u] - p2[u].
那么具体看几个简单例题
HDU - 3887 传送门
//题意: 问你对于每个节点,它的子树上标号比它小的点有多少个
//思路: 子树的问题,dfs序可以很轻松的解决,因为点在它的子树上,所以在线段树中,必定在它的两个时间戳的区间之间,所以我们只需要从小到大考虑,它的区间里有多少个点已经放了,然后再把它放进去. 很容易的解决了 . DFS 序的入门题.
AC Code
/** @Cain*/const int maxn = 1e5+5;int cas=1;int cnt,head[maxn];int n,root,ti;int p1[maxn],p2[maxn]; //记录树上的每个点遍历时它的次序.struct node{ int to,next;}s[maxn*2];void add(int u,int v){ s[cnt].to = v; s[cnt].next = head[u]; head[u] = cnt++;}void dfs_id(int u,int fa){ p1[u] = ++ti; for(int i=head[u]; ~i ; i = s[i].next){ int to = s[i].to; if(fa == to) continue; dfs_id(to,u); } p2[u] = ti;}int sum[maxn*4];void pushup(int rt){ sum[rt] = sum[rt<<1] + sum[rt<<1|1];}void build(int l,int r,int rt){ sum[rt] = 0; if(l == r) return; int mid = (l+r)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1);}void update(int l,int r,int rt,int pos){ if(l == r){ sum[rt]++; return ; } int mid = (l+r)>>1; if(pos<=mid) update(l,mid,rt<<1,pos); else update(mid+1,r,rt<<1|1,pos); pushup(rt);}int query(int l,int r,int rt,int ql,int qr){ if(ql<=l && r<=qr) return sum[rt]; int mid = (l+r) >> 1; int res = 0; if(ql <= mid) res += query(l,mid,rt<<1,ql,qr); if(qr > mid) res += query(mid+1,r,rt<<1|1,ql,qr); return res;}void solve(){ while(~scanf("%d%d",&n,&root)){ if(n + root == 0) break; Fill(head,-1); cnt = ti = 0; for(int i=1;i<=n-1;i++){ int u,v; scanf("%d%d",&u,&v); add(u,v); add(v,u); } dfs_id(root,-1); /*for(int i=1;i<=n;i++){ printf("%d %d \n",p1[i],p2[i]); }*/ build(1,n,1); for(int i=1;i<=n;i++){ printf("%d%c",query(1,n,1,p1[i],p2[i]),i==n?'\n':' '); update(1,n,1,p1[i]); } }}
poj - 3321 传送门
//题意: 一开始告诉你树上每个节点都有1个苹果,然后你对一个节点操作,如果有苹果,就拿走,没苹果,就放上,然后询问你以x为根的子树上有多少个苹果.
//思路: 有上面那道题的基础, 我相信这道题是非常简单的吧. 那么直接做呗. DFS序水题.
AC Code
/** @Cain*/const int maxn = 1e5+5;int cas=1;int cnt,head[maxn];int n,ti;int p1[maxn],p2[maxn]; //记录树上的每个点遍历时它的次序.struct node{ int to,next;}s[maxn*2];void add(int u,int v){ s[cnt].to = v; s[cnt].next = head[u]; head[u] = cnt++;}void dfs_id(int u,int fa){ p1[u] = ++ti; for(int i=head[u]; ~i ; i = s[i].next){ int to = s[i].to; if(fa == to) continue; dfs_id(to,u); } p2[u] = ti;}int sum[maxn*4];void pushup(int rt){ sum[rt] = sum[rt<<1] + sum[rt<<1|1];}void build(int l,int r,int rt){ if(l == r) { sum[rt] = 1; return; } int mid = (l+r)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); pushup(rt);}void update(int l,int r,int rt,int pos){ if(l == r){ if(sum[rt]) sum[rt] = 0; else sum[rt] = 1; return ; } int mid = (l+r)>>1; if(pos<=mid) update(l,mid,rt<<1,pos); else update(mid+1,r,rt<<1|1,pos); pushup(rt);}int query(int l,int r,int rt,int ql,int qr){ if(ql<=l && r<=qr) return sum[rt]; int mid = (l+r) >> 1; int res = 0; if(ql <= mid) res += query(l,mid,rt<<1,ql,qr); if(qr > mid) res += query(mid+1,r,rt<<1|1,ql,qr); return res;}void solve(){ while(~scanf("%d",&n)){ Fill(head,-1); cnt = ti = 0; for(int i=1;i<=n-1;i++){ int u,v; scanf("%d%d",&u,&v); add(u,v); add(v,u); } dfs_id(1,-1); /*for(int i=1;i<=n;i++){ printf("%d %d \n",p1[i],p2[i]); }*/ int m; scanf("%d",&m); build(1,n,1); while(m--){ char s[10]; scanf("%s",s); if(s[0] == 'Q') { int u; scanf("%d",&u); printf("%d\n",query(1,n,1,p1[u],p2[u])); } else { int u; scanf("%d",&u); update(1,n,1,p1[u]); } } }}
阅读全文
0 0
- DFS序的学习
- dfs序专题学习
- BFS & DFS的基础学习
- DFS学习借鉴的博客
- 【DFS序的常见问题】
- 树的DFS序
- 树的dfs序
- DFS学习
- 图的BFS和DFS学习笔记
- 对DFS序的理解
- 算法学习 - 图的深度优先遍历(DFS) (C++)
- 算法学习:图的深度优先遍历(DFS)
- 学习笔记-DTFT、DFS和DFT的联系
- 回溯,BFS,DFS学习
- dfs学习总结
- BFS&&DFS学习
- DFS学习笔记
- DFS学习归纳总结
- 字节对齐规则
- <<征服C指针>>学习笔记
- 云唯+CEO李宏洋谈:IT培训学费辣么贵还值得去吗?
- Retrofit2.0的使用之添加请求头
- XlistView
- DFS序的学习
- CSS3笔记——过渡 Transition
- 给定一个字符串s,请计算输出含有连续两个s作为子串的最短字符串。
- 完全背包
- Unity鼠标出屏幕后 摄像机跟随鼠标方向移动
- Luba And The Ticket CodeForces
- OKHTTP的简单封装
- 疯狂Java讲义:第16章:多线程复习(一)
- 如何在协议栈中构建自己的 Zigbee 网络指示灯