[dfs序]猴猴的比赛
Posted yuxiaoze
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[dfs序]猴猴的比赛相关的知识,希望对你有一定的参考价值。
题目限制
2000 ms 256 M
题目描述
猴猴今天要和小伙伴猩猩比赛爬树,为了公平不碰撞,猴猴和猩猩需要在不同的树上攀爬。于是
它们选了两颗节点数同为n的树,并将两棵树的节点分别以1~n标号(根节点标号为1),但两棵树
的节点连接方式不尽相同。
现在它们决定选择两个标号的点进行比赛。为了方便统计,规定它们比赛中必须都向上爬。(即
选定的赛段节点u→节点v都必须指向叶子方向)请你求出这两棵树上共有多少对节点满足比赛的需
求。
输入格式
第一行一个数n。(n≤100000)
接下来n-1行,每行2个数a和b,表示第一棵树a和b有树枝相连。
接下来n-1行,每行2个数a和b,表示第二棵树a和b有树枝相连。
输出格式
输出满足条件的对数。
数据范围
对于30%的数据:n≤1000
对于50%的数据:n≤10000
对于100%的数据:n≤100000,1≤a,b≤n
输入样例
输入样例1
4
1 2
2 3
3 4
1 2
2 3
2 4
输入样例2
7
1 2
1 3
2 4
1 5
5 6
6 7
1 2
1 3
3 4
4 5
3 6
1 7
输入样例3
4
1 2
1 3
3 4
1 2
1 3
3 4
输出样例
输出样例1
5
输出样例2
6
输出样例3
4
题解
我们可以通过dfs序对第一棵树进行编号,得到每个节点本身的编号以及子树的编号范围[li,ri]
。 用树状数组来维护后面的计算。 在DFS处理第二棵树时,我们每处理完一个节
点,就将该节点在第一棵树中的对应编号设为1,处理完所有子节点后,查询编号区间 [li,ri]
的区间和,即当前子树下,有多少个节点在树1中也是当前节点的子孙节点。维护计数即可。 复杂
度 nlog(n).
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 const int N=100000+5; 5 6 int n,num,last[N],nxt[2*N],ver[2*N]; 7 inline void add(int x,int y) 8 {nxt[++num]=last[x]; last[x]=num; ver[num]=y; 9 nxt[++num]=last[y]; last[y]=num; ver[num]=x; 10 } 11 int id,ord[N],siz[N]; 12 void pre(int x,int fa) 13 {ord[x]=++id; siz[x]=1; 14 for(int i=last[x];i;i=nxt[i]) 15 {int y=ver[i]; 16 if(y==fa) continue; 17 pre(y,x); siz[x]+=siz[y]; 18 } 19 } 20 int lowbit[N],t[N],ans[N]; 21 inline void change(int x,int delta) 22 {while(x<=n) 23 {t[x]+=delta; 24 x+=lowbit[x]; 25 } 26 } 27 inline int ask(int x) 28 {int re=0; 29 while(x) 30 {re+=t[x]; 31 x-=lowbit[x]; 32 } 33 return re; 34 } 35 void dfs(int x,int fa) 36 {int cmp=0; 37 for(int i=last[x];i;i=nxt[i]) 38 {int y=ver[i]; 39 if(y==fa) continue; 40 cmp=ask(ord[y]+siz[y]-1)-ask(ord[y]-1); 41 dfs(y,x); 42 ans[y]-=cmp; 43 change(ord[y],1); 44 } 45 ans[x]=ask(ord[x]+siz[x]-1)-ask(ord[x]-1); 46 } 47 int main() 48 { 49 freopen("climb.in","r",stdin); 50 freopen("climb.out","w",stdout); 51 int x,y; scanf("%d",&n); 52 for(int i=1;i<n;i++) {scanf("%d%d",&x,&y); add(x,y);} 53 pre(1,0); 54 num=0; memset(last,0,sizeof(last)); 55 for(int i=1;i<n;i++) {scanf("%d%d",&x,&y); add(x,y); } 56 for(int i=1;i<=n;i++) lowbit[i]=i&-i; 57 58 dfs(1,0); 59 for(int i=1;i<=n;i++) ans[0]+=ans[i]; 60 printf("%d",ans[0]); 61 return 0; 62 }
以上是关于[dfs序]猴猴的比赛的主要内容,如果未能解决你的问题,请参考以下文章