1787: [Ahoi2008]Meet 紧急集合

Time Limit: 20 Sec  Memory Limit: 162 MB

Submit: 3578  Solved: 1635

[Submit][Status][Discuss]

Description

Input

Output

Sample Input

6 4


1 2

2 3

2 4

4 5

5 6

4 5 6

6 3 1

2 4 4

6 6 6

Sample Output



5 2

2 5

4 1

6 0

HINT

点很少,只有三个,画一下图,手动模拟一下就会发现:我们要求的就是画一条线将三个点连起来,使线最短

由于树路径的唯一性,连接三个点的路径是唯一的,但是由于走法的不同会导致因为重复部分路径而使路径增长

未使路径最短,我们就不能走复路,所以我们只需求出三者最大的LCA,再将另外一个点走上LCA所在路径就好了

如图:

具体LCA用倍增实现,复杂度O(mlogn + nlogn),一个是预处理,一个是询问

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next)
using namespace std;
const int maxn = 500005,maxm = 1000005,INF = 1000000000;
inline int RD(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
return out * flag;
}
int dep[maxn],fa[maxn][20];
int N,M,head[maxn],nedge = 0,p[4];
struct node{int lca,u,v;}e[4];
struct EDGE{int to,next;}edge[maxm];
inline void build(int u,int v){
edge[nedge] = (EDGE){v,head[u]}; head[u] = nedge++;
edge[nedge] = (EDGE){u,head[v]}; head[v] = nedge++;
}
void dfs(int u,int f,int d){
dep[u] = ++d; fa[u][0] = f;
Redge(u) if (edge[k].to != f) dfs(edge[k].to,u,d);
}
void init(){REP(j,19) REP(i,N) fa[i][j] = fa[fa[i][j - 1]][j - 1];}
int LCA(int u,int v){
if (dep[u] < dep[v]) u ^= v ^= u ^= v;
int d = dep[u] - dep[v];
for (int i = 0; (1 << i) <= d; i++)
if ((1 << i) & d) u = fa[u][i];
if (u == v) return u;
for (int i = 19; i >= 0; i--)
if (fa[u][i] != fa[v][i]) u = fa[u][i],v = fa[v][i];
return fa[u][0];
}
void B_Sort(){
for (int i = 1; i <= 3; i++)
for (int j = i + 1; j <= 3; j++)
if (dep[e[i].lca] > dep[e[j].lca]) swap(e[i],e[j]);
}
void solve(){
int ans,u;
while (M--){
REP(i,3) p[i] = RD();
for (int i = 1,k = 0; i < 3; i++)
for (int j = i + 1; j <= 3; j++)
e[++k].u = i,e[k].v = j,e[k].lca = LCA(p[i],p[j]);
B_Sort();
//REP(i,3) printf("%d and %d lca: %d\n",e[i].u,e[i].v,e[i].lca);
REP(i,3) if (i != e[1].u && i != e[1].v) {u = p[i];break;}
ans = dep[p[e[1].u]] + dep[p[e[1].v]] + dep[u] - 2 * dep[e[1].lca] - dep[e[3].lca];
printf("%d %d\n",e[3].lca,ans);
}
}
int main(){
memset(head,-1,sizeof(head));
N = RD(); M = RD();
REP(i,N - 1) build(RD(),RD());
dfs(1,0,0); init();
solve();
return 0;
}

BZOJ1787 [Ahoi2008]Meet 紧急集合 【LCA】的更多相关文章

  1. BZOJ1787 [Ahoi2008]Meet 紧急集合 LCA

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1787 题意概括 有一棵节点为n个(n≤500000)的树.接下来m次询问(m≤500000),每次 ...

  2. bzoj1787[Ahoi2008]Meet 紧急集合&bzoj1832[AHOI2008]聚会

    bzoj1787[Ahoi2008]Meet 紧急集合 bzoj1832[AHOI2008]聚会 题意: 给个树,每次给三个点,求与这三个点距离最小的点. 题解: 倍增求出两两之间的LCA后,比较容易 ...

  3. 【BZOJ1787】[Ahoi2008]Meet 紧急集合 LCA

    [BZOJ1787][Ahoi2008]Meet 紧急集合 Description Input Output Sample Input 6 4 1 2 2 3 2 4 4 5 5 6 4 5 6 6 ...

  4. bzoj1787 [Ahoi2008]Meet 紧急集合

    1787: [Ahoi2008]Meet 紧急集合 Time Limit: 20 Sec  Memory Limit: 162 MB Submit: 2272  Solved: 1029 [Submi ...

  5. BZOJ 1787: [Ahoi2008]Meet 紧急集合 LCA

    1787: [Ahoi2008]Meet 紧急集合 Description Input Output Sample Input 6 4 1 2 2 3 2 4 4 5 5 6 4 5 6 6 3 1 ...

  6. 【块状树】【LCA】bzoj1787 [Ahoi2008]Meet 紧急集合

    分块LCA什么的,意外地快呢…… 就是对询问的3个点两两求LCA,若其中两组LCA相等,则答案为第三者. 然后用深度减一减什么的就求出距离了. #include<cstdio> #incl ...

  7. [bzoj1787][Ahoi2008]Meet 紧急集合(lca)

    传送门 可以看出,三个点两两之间的lca会有一对相同,而另一个lca就是聚集点. 然后搞搞就可以求出距离了. ——代码 #include <cstdio> #include <cst ...

  8. BZOJ1787 [Ahoi2008]Meet 紧急集合[结论题]

    location. 求到树上三点距离和最短的点及此距离. 这个不还是分类讨论题么,分两类大情况,如下图. 于是乎发现三个点对的lca中较深的那个lca是答案点.距离就是两两点对距离加起来除以2即可.这 ...

  9. LCA 【bzoj1787】[Ahoi2008]Meet 紧急集合

    LCA [bzoj1787][Ahoi2008]Meet 紧急集合 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1787 注意到边权为一 ...

随机推荐

  1. laravel构造函数跳转失败

    <?php namespace App\Http\Controllers\Admin; use Illuminate\Http\Request; use App\Http\Requests;us ...

  2. Nginx反向代理 Laravel获取真实IP地址(PHP)

    使用VUE前后端分离开发 后端使用Laravel  想要获取到用户的真实IP地址 因为分离开发不同源跨域问题 所以只能进行前端Nginx反向代理 location /api { rewrite ^/a ...

  3. 清华大学《C++语言程序设计基础》线上课程笔记01---基础概念与一些注意事项

    使用除法的注意事项 double b = 4.0 * 1/239.0; 因为整数相除结果取整,如果参数写1/239,结果就都是0 浮点数注意事项 浮点数是近似存储,所以不能直接比较两个浮点数的大小, ...

  4. Test类实验

    package PC_TEST; class CPU{ int speed; CPU(){ speed=0; } CPU(int k){ speed=k; } void setSpeed(int k) ...

  5. JENKINS系统的安装部署

    JENKINS 安装使用文档 简介 Jenkins是一个功能强大的应用程序,允许持续集成和持续交付项目,无论用的是什么平台.这是一个免费的源代码,可以处理任何类型的构建或持续集成,集成Jenkins可 ...

  6. C++基础语言知识大汇总(不断更新!!!)

    经过十天的时间,LITTLESUN做好了前期的工作,今天LITTLESUN就要在新地图里扬帆起航喽!!!(撒花) 简单的整理了一下这次启航准备好的物资.后面的航程中也会不断来补充这个小仓库哦!

  7. 用Kettle的一套流程完成对整个数据库迁移 费元星

    原地址 :http://ainidehsj.iteye.com/blog/1735434 需求: 1.你是否遇到了需要将mysql数据库中的所有表与数据迁移到Oracle. 2.你是否还在使用kett ...

  8. C++学习007-使用exit退出进程

    使用exit可以实现退出当前进程. 如下 在程序接收到一个字符后,就退出进程 编写环境 vs2015 int main() { int a = 10, b = 20; std::cout <&l ...

  9. 第三十四篇 Python面向对象之 反射(自省)

    什么是反射? 反射的概念是由Smith在1982年提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省).这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它首先被程序语 ...

  10. 验证码 java实现的程序

    makeCheckcode.java package pic; import java.awt.Color; import java.awt.Font; import java.awt.Graphic ...