首页 > 其他分享 >6576: 点的距离 倍增LCA

6576: 点的距离 倍增LCA

时间:2023-09-15 15:57:30浏览次数:31  
标签:cnt 6576 int -- dep add LCA return 倍增

描述

 

给定一棵 n 个点的树,Q 个询问,每次询问点 x 到点 y 两点之间的距离。

 

输入

 

第一行一个正整数 n,表示这棵树有 n 个节点;

接下来 n−1 行,每行两个整数 x,y表示 x,y 之间有一条连边;

然后一个整数 Q,表示有 Q 个询问;

接下来 Q 行每行两个整数 x,y 表示询问 x 到 y 的距离。

对于全部数据,1≤n≤105,1≤x,y≤n

 

输出

 

输出 Q 行,每行表示每个询问的答案。

 

样例输入

 

6
1 2
1 3
2 4
2 5
3 6
2
2 6
5 6

样例输出

3
4

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+10,inf = 0x3f3f3f3f;
struct node{
    int to,next,w; 
    //to:第cnt条边的终点 
    //next:第cnt条边的起点的上一条边是第几条边
    //w:第cnt条边的权值 
};
node edge[2 * N];
int head[2 * N],cnt = 1; //链式前向星数组大小2 * N,边数从1开始 
int n,m,x,y;
int dep[N],f[N][21]; //dep[i]第i个点当前的深度,f[i][k]表示第i个点向上2^k层的父节点是谁 
void add(int u,int v)
{
    edge[cnt].to = v;
    edge[cnt].next = head[u];
    head[u] = cnt++;
}
void init(int u,int fa)
{
    dep[u] = dep[fa] + 1;
    for(int i = 1; (1<<i) <= dep[u]; i++)
        f[u][i] = f[f[u][i - 1]][i - 1];
    for(int i = head[u]; i; i = edge[i].next)
    {
        int v = edge[i].to;
        if(v == fa)continue;
        f[v][0] = u;
        init(v,u);
    }
}
int lca(int x,int y)
{
    if(dep[x] < dep[y])swap(x,y);
    for(int i = 20; i >= 0; i--)
    {
        if(dep[f[x][i]] >= dep[y]) x = f[x][i]; //深度还没有统一
        if(x == y)return x; 
    }
    for(int i = 20; i >= 0; i--)
    {
        if(f[x][i] != f[y][i])
        {
            x = f[x][i],y = f[y][i];
        }
    }
    return f[x][0]; //x往前再走一步就是x,y的最近公共祖先 
}
int dist(int x,int y)
{
    return dep[x] + dep[y] - 2 * dep[lca(x,y)];
}
int main()
{
    cin >> n;
    for(int i = 1; i < n; i++)
    {
        scanf("%d %d",&x,&y);
        add(x,y);
        add(y,x);
    }
    init(1,0);
    cin >> m;
    while(m--)
    {
        scanf("%d %d",&x,&y);
        printf("%d\n",dist(x,y));
    }
     return 0;
}

 

标签:cnt,6576,int,--,dep,add,LCA,return,倍增
From: https://www.cnblogs.com/jyssh/p/17705174.html

相关文章

  • 倍增并查集
    假如说我们有\(n\)个元素,\(m\)次操作。每次操作给定\(x,y,z\),要求对于任意\(0\lei\lez\),将\(x+i\)和\(y+i\)合并,求最后的并查集形态。数据范围是\(10^5\)级别的。我们考虑将\(z\)二进制拆分,那么可以将\(z\)分解为\(O(\logn)\)个\(2\)的整数次幂之和,也就可......
  • C++算法进阶系列之倍增算法解决求幂运算
    1.引言学习倍增算法,先了解什么是倍增以及倍增算法的优势。如果面前有一堆石子,要求计算出石子的总数量。这是一个简单的数数问题,可以:一颗石子一颗石子的数。两颗石子两颗石子的数。三颗石子三颗石子的数。或者更多颗石子更多颗石子的数……在石子很多的情况下,每一次选择更......
  • 科技:dfn 求 LCA
    upd:2023.09.13新建非常好思路,学习自Alex_Wei。摘要使用st表维护区间内所有点的dfn最小的父节点。优点是好写、时间空间常数小。前置约定\(dfn_{i}\):\(i\)是第几个被访问的点\(sub_{i}\):以\(i\)为根的子树\(LCA\):\(\text{LCA}(u,v)\)原理dfn的性质:设\(......
  • 【模板】最近公共祖先LCA——倍增
    题目来自洛谷P3379【模板】最近公共祖先(LCA)【模板】最近公共祖先(LCA)题目描述如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。输入格式第一行包含三个正整数\(N,M,S\),分别表示树的结点个数、询问的个数和树根结点的序号。接下来\(N-1\)行每行包含两个正整数......
  • 倍增求lca
    步骤:1.前置准备:lg数组,depth数组,fa数组2.若x与y不在同一深度,先让它们跳到同一深度3.开始倍增往上跳代码:#include<iostream>#include<cstdio>usingnamespacestd;constlonglongN=1e6+10;intn,m,s,h1,h2,lg[N],fa[500010][30],depth[N];inttot=0,head[N],nxt[N],v[N......
  • IU86751低空载电流,40倍增益免滤波,2X28W双声道或50W音频放大器
    IU86751E是一款2x28W立体声;在单声道使用的情况下;最高可输出50W高效D类音频功率放大电路。先进的EMI抑制技术使得在输出端口采用廉价的铁氧体磁珠滤波器就可以满足EMC要求。IU86751E音频功率放大器是为需要输出高质量音频功率的系统设计的,它采用表面贴装技术,只需少量的外围器件,便使......
  • 第 360 场周赛 (二进制枚举、树上倍增)
    2833. 距离原点最远的点 本题要求最远的距离,所有‘_’必须全为左或全为右。利用前缀和的思想看看L多还是R多,最后加上_的数目就是答案。classSolution{public:intfurthestDistanceFromOrigin(stringmoves){intn=moves.size();inttt=0,l......
  • VirtualCamera虚拟相机实时拍照教程
    VirtualCamera虚拟相机实时拍照教程简介说明:虚拟相机实时拍照可以替换一些app需要实时拍照,但不能选择本地相册图片的应用,当使用该应用的时候,可以做到将相册中的照片替换成实时拍照的照片,以做到某些条件下无法实时拍照的要求。一、适用机型及系统1、机型:iphone6、6s、6p、7、7p、......
  • VirtualCamera虚拟相机实时视频使用教程
    VirtualCamera虚拟相机实时视频使用教程简介说明VirtualCamera虚拟相机实时视频主要用于直播平台带货直播,无人直播,视频通话等场景,视频时长不限,大小不限,高清实时替换,可动态调节快慢。注意,使用过程中视频声音是无法发送过去的,声音来着外部接收,就如我们视频通话时一样,声音来自外部。......
  • Codeforces Round 885 (Div. 2) F. Vika and Wiki(数学,倍增)
    题目链接:https://codeforces.com/problemset/problem/1848/F 大致题意:长度为n(n是2的幂次),每轮让a【i】=a【i】^a【i%n+1】,(^为异或)问需要操作多少次后可以使得每个数为0; 解题思路:我们来观察:第一次相当于:a【i】=a【i】^a【i+1】,a【i+1】=a【i+1】^a【i+2】第二次......