[10.2模拟] tree

本文介绍了一种解决树形结构中查询问题的有效方法——树上倍增算法。该算法可以快速判断两个节点是否位于同一链上,并通过递归DFS预处理节点的深度和父节点信息,最终实现高效查询。

题意:给你一棵树,m次询问,每次询问(a,b),即a和b是否在一条链上

题解:

树上倍增

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define RG register
#define N 200010
using namespace std;

int n,qu,e_num;
int nxt[N*2],to[N*2],h[N],siz[N],dep[N],fa[N][22];

inline int gi() {
  int x=0,o=1; char ch=getchar();
  while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
  if(ch=='-') o=-1,ch=getchar();
  while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
  return o*x;
}

inline void add(int x, int y) {
  nxt[++e_num]=h[x],to[e_num]=y,h[x]=e_num;
}

inline int find(int y, int x) {
  for(int j=20; j>=0; j--) {
    if(dep[fa[y][j]]>dep[x] && fa[y][j]) y=fa[y][j];
  }
  return y;
}

inline void dfs(int u) {
  siz[u]=1;
  for(int i=h[u]; i; i=nxt[i]) {
    int v=to[i];
    if(v==fa[u][0]) continue;
    fa[v][0]=u,dep[v]=dep[u]+1;
    dfs(v);
    siz[u]+=siz[v];
  }
}

int main() {
  n=gi(),qu=gi();
  for(RG int i=1; i<n; i++) {
    int x=gi(),y=gi();
    add(x,y),add(y,x);
  }
  dep[1]=1;
  dfs(1);
  for(int j=1; j<=20; j++)
    for(int i=1; i<=n; i++)
      fa[i][j]=fa[fa[i][j-1]][j-1];
  for(int i=1; i<=qu; i++) {
    int x=gi(),y=gi(),z;
    if(dep[x]>dep[y]) swap(x,y);
    z=find(y,x);
    if(fa[z][0]!=x) printf("%d\n", siz[x]+siz[y]);
    else printf("%d\n", siz[y]+n-siz[z]);
  }
  return 0;
}

转载于:https://www.cnblogs.com/HLXZZ/p/7625197.html

bingda@robot:~$ sudo apt update [sudo] password for bingda: Get:1 file:/var/cuda-repo-10-2-local-10.2.89 InRelease Ign:1 file:/var/cuda-repo-10-2-local-10.2.89 InRelease Get:2 file:/var/visionworks-repo InRelease Ign:2 file:/var/visionworks-repo InRelease Get:3 file:/var/visionworks-sfm-repo InRelease Ign:3 file:/var/visionworks-sfm-repo InRelease Get:4 file:/var/visionworks-tracking-repo InRelease Ign:4 file:/var/visionworks-tracking-repo InRelease Get:5 file:/var/cuda-repo-10-2-local-10.2.89 Release [574 B] Get:6 file:/var/visionworks-repo Release [2,001 B] Get:7 file:/var/visionworks-sfm-repo Release [2,005 B] Get:8 file:/var/visionworks-tracking-repo Release [2,010 B] Get:5 file:/var/cuda-repo-10-2-local-10.2.89 Release [574 B] Get:6 file:/var/visionworks-repo Release [2,001 B] Get:7 file:/var/visionworks-sfm-repo Release [2,005 B] Get:8 file:/var/visionworks-tracking-repo Release [2,010 B] Hit:14 http://ppa.launchpad.net/graphics-drivers/ppa/ubuntu bionic InRelease Hit:15 https://mirror.tuna.tsinghua.edu.cn/ubuntu-ports bionic InRelease Hit:13 https://packages.microsoft.com/repos/code stable InRelease Hit:17 https://mirror.tuna.tsinghua.edu.cn/ubuntu-ports bionic-updates InRelease Hit:18 https://mirror.tuna.tsinghua.edu.cn/ubuntu-ports bionic-backports InRelease Hit:19 https://mirror.tuna.tsinghua.edu.cn/ubuntu-ports bionic-security InRelease Ign:20 https://mirror.tuna.tsinghua.edu.cn/ros/ubuntu bionic InRelease Hit:22 https://mirror.tuna.tsinghua.edu.cn/ros/ubuntu bionic Release Hit:16 https://repo.download.nvidia.cn/jetson/common r32.4 InRelease Hit:21 https://repo.download.nvidia.cn/jetson/t210 r32.4 InRelease Reading package lists... Done Building dependency tree Reading state information... Done 754 packages can be upgraded. Run 'apt list --upgradab
03-27
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值