给出一棵树,许多询问,每次询问A,B,C三点,求一点使到三点距离最小,输出该点和最小值。

很明显就是求LCA,三种组合都求一次LCA,然后在里面选个距离和最小的就行了。

官方题解里面的代码求LCA是在线DFS RMQ的方法..先记录欧拉序,且记录某个点在序列里的第一个位置,每次询问a,b的LCA就是询问两者在欧拉序列里第一个位置之差中的那些点里面深度最小的

LCA(a,b)=RMQ(dep, pos[a], pos[b])

/** @Date    : 2017-09-27 20:41:28
* @FileName: CS20 C LCA RMQ.cpp
* @Platform: Windows
* @Author : Lweleth (SoungEarlf@gmail.com)
* @Link : https://github.com/
* @Version : $Id$
*/
#include <bits/stdc++.h>
#define LL long long
#define PII pair<int ,int>
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std; const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8; int dep[N];
int pos[N];
int rmq[19][2*N];
int eul[2*N], c, l[2*N]; vector<int> edg[N]; void dfs(int x, int pre)
{
eul[++c] = x;
pos[x] = c;
if(pre) dep[x] = dep[pre] + 1;
for(auto i: edg[x])
{
if(i == pre)
continue;
dfs(i, x);
eul[++c] = x;
}
} void init()
{
dfs(1, 0);
for(int i = 2; i <= c; i++)//预处理 2^k=x对应的k
l[i] = l[i / 2] + 1;
for(int i = 1; i <= c; i++)
rmq[0][i] = eul[i];
for(int j = 1; (1 << j) <= c; j++)
for(int i = 1; i <= c; i++)
{
rmq[j][i] = rmq[j - 1][i];
if(i + (1 << (j - 1)) > c)
continue;
if(dep[rmq[j - 1][i + (1 << (j - 1))]] < dep[rmq[j][i]])
rmq[j][i] = rmq[j - 1][i + (1 << (j - 1))];
}
} int lca(int x, int y)
{
if(pos[x] > pos[y])
swap(x, y);
int dis = pos[y] - pos[x] + 1;
int k = l[dis];
if(dep[rmq[k][pos[x] + dis - (1 << k)]]
< dep[rmq[k][pos[x]]])
return rmq[k][pos[x] + dis - (1 << k)];
else return rmq[k][pos[x]];
} int distance(int a, int b)
{
int ac = lca(a, b);
return dep[a] + dep[b] - 2 * dep[ac];
}
int main()
{
int n, q;
cin >> n >> q;
for(int i = 0; i < n - 1; i++)
{
int x, y;
scanf("%d%d", &x, &y);
edg[x].PB(y);
edg[y].PB(x);
}
init();
while(q--)
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
int ac1 = lca(a, b);
int ac2 = lca(a, c);
int ac3 = lca(b, c);
int ans1 = distance(ac1, a) + distance(ac1, b) + distance(ac1, c);
int ans2 = distance(ac2, a) + distance(ac2, b) + distance(ac2, c);
int ans3 = distance(ac3, a) + distance(ac3, b) + distance(ac3, c);
if(ans1 > ans2)
swap(ans1, ans2), swap(ac1, ac2);
if(ans1 > ans3)
swap(ans1, ans3), swap(ac1, ac3);
printf("%d %d\n", ac1, ans1);
}
return 0;
}

CS20 D LCA的更多相关文章

  1. BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]

    3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 1280 MBSubmit: 3127  Solved: 795[Submit][Status][Discu ...

  2. BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2050  Solved: 817[Submit][Status ...

  3. [bzoj3123][sdoi2013森林] (树上主席树+lca+并查集启发式合并+暴力重构森林)

    Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...

  4. [bzoj2588][count on a tree] (主席树+lca)

    Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...

  5. [板子]倍增LCA

    倍增LCA板子,没有压行,可读性应该还可以.转载请随意. #include <cstdio> #include <cstring> #include <algorithm ...

  6. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

  7. [bzoj3626][LNOI2014]LCA

    Description 给出一个$n$个节点的有根树(编号为$0$到$n-1$,根节点为$0$). 一个点的深度定义为这个节点到根的距离$+1$. 设$dep[i]$表示点$i$的深度,$lca(i, ...

  8. (RMQ版)LCA注意要点

    inline int lca(int x,int y){ if(x>y) swap(x,y); ]][x]]<h[rmq[log[y-x+]][y-near[y-x+]+]])? rmq[ ...

  9. bzoj3631: [JLOI2014]松鼠的新家(LCA+差分)

    题目大意:一棵树,以一定顺序走完n个点,求每个点经过多少遍 可以树链剖分,也可以直接在树上做差分序列的标记 后者打起来更舒适一点.. 具体实现: 先求x,y的lca,且dep[x]<dep[y] ...

随机推荐

  1. java中static使用之静态方法注意点

    1.静态方法可以直接调用同类中的静态成员,但是不能直接调用非静态成员,这是为什么呢?大家想一下,静态成员在对象创建之前就要写入内存,所以它在内存中是实实在在的存在的,而非静态还不存在内存中,所以不能调 ...

  2. MIT挑战(如何在12个月内自学完成MIT计算机科学的33门课程|内附MIT公开课程资源和学习顺序

    译者注:本文译自Scott H. Young的博客,Scott拥有超强的学习能力,曾在12个月内自学完成麻省理工学院计算机科学的33门课程.本文就是他个人对于这次MIT挑战的介绍和总结. 版权声明:本 ...

  3. SDWebImage缓存图片的机制

    SDWebImage是一个很厉害的图片缓存的框架.既ASIHttp+AsyncImage之后,我一直使用AFNetworking集成的UIImageView+AFNetworking.h,但后者对于图 ...

  4. Android封装TitleBar基本适用所有常规开发

    Android封装TitleBar基本适用所有常规开发 github地址:https://github.com/SiberiaDante/SiberiaDanteLib/blob/master/sib ...

  5. C语言词频统计设计

    项目需求: 1.设计一个词频统计小软件,对给定的英文文章进行单词频率的统计. 2.文章中相应的标点不计入统计. 3.将统计结果以从大到小的排序方式输出. 设计: 1.因为功能相对简单,采用C语言直接进 ...

  6. mysql索引的优化

    MySQL索引的优化 上面都在说使用索引的好处,但过多的使用索引将会造成滥用.因此索引也会有它的缺点:虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT.UPDATE和DEL ...

  7. SpringBoot(十三)_springboot上传Excel并读取excel中的数据

    今天工作中,发现同事在整理数据,通过excel上传到数据库.所以现在写了篇利用springboot读取excel中的数据的demo.至于数据的进一步处理,大家肯定有不同的应用场景,自行修改 pom文件 ...

  8. Redis(一) 安装

    选择在Linux下安装redis,现在采用虚拟机安装的centos7 进行安装的 1.安装gcc yum install gcc-c++ 2.下载redis安装包,在root目录下执行 wget ht ...

  9. 如何调换antd中Modal对话框确认按钮和取消按钮两个按钮的位置

    今天有个工作是把所有的确认按钮放在取消按钮的左边,类似于下图这样的,公司用的时antd组件 但是antd组件的按钮时确认键放在右边的 可以采用下面的方式,将按钮调换过来: 对的,就是在modal里面的 ...

  10. java 加载过程

    1.main方法进入方法区 2.main方法进栈 3.调用xxx类加载到jvm中 类属性进入数据共享区,方法进入到方法区