P4281 [AHOI2008]紧急集合 / 聚会

题目描述

欢乐岛上有个非常好玩的游戏,叫做“紧急集合”。在岛上分散有N个等待点,有N-1条道路连接着它们,每一条道路都连接某两个等待点,且通过这些道路可以走遍所有的等待点,通过道路从一个点到另一个点要花费一个游戏币。

参加游戏的人三人一组,开始的时候,所有人员均任意分散在各个等待点上(每个点同时允许多个人等待),每个人均带有足够多的游戏币(用于支付使用道路的花费)、地图(标明等待点之间道路连接的情况)以及对话机(用于和同组的成员联系)。当集合号吹响后,每组成员之间迅速联系,了解到自己组所有成员所在的等待点后,迅速在N个等待点中确定一个集结点,组内所有成员将在该集合点集合,集合所用花费最少的组将是游戏的赢家。

小可可和他的朋友邀请你一起参加这个游戏,由你来选择集合点,聪明的你能够完成这个任务,帮助小可可赢得游戏吗?

输入格式

第一行两个正整数N和M(N<=500000,M<=500000),之间用一个空格隔开。分别表示等待点的个数(等待点也从1到N进行编号)和获奖所需要完成集合的次数。 随后有N-1行,每行用两个正整数A和B,之间用一个空格隔开,表示编号为A和编号为B的等待点之间有一条路。 接着还有M行,每行用三个正整数表示某次集合前小可可、小可可的朋友以及你所在等待点的编号。

输出格式

一共有M行,每行两个数P,C,用一个空格隔开。其中第i行表示第i次集合点选择在编号为P的等待点,集合总共的花费是C个游戏币。

输入输出样例

输入 #1复制

6 4
1 2
2 3
2 4
4 5
5 6
4 5 6
6 3 1
2 4 4
6 6 6
输出 #1复制

5 2
2 5
4 1
6 0

说明/提示

提示:

40%的数据中N<=2000,M<=2000
100%的数据中,N<=500000,M<=500000

sol:答案很显然应该是lca,用st表求lca,三个lca中应该有两个是相同的,就是走到另一个lca最优,距离和就是三个节点的深度-三个lca的深度

#include <bits/stdc++.h>
using namespace std;
typedef int ll;
inline ll read()
{
ll s=; bool f=; char ch=' ';
while(!isdigit(ch)) {f|=(ch=='-'); ch=getchar();}
while(isdigit(ch)) {s=(s<<)+(s<<)+(ch^); ch=getchar();}
return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
if(x<) {putchar('-'); x=-x;}
if(x<) {putchar(x+''); return;}
write(x/); putchar((x%)+'');
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const int N=,M=;
int n,m,nn;
int tot=,Next[M],to[M],head[N];
int clk=,id[N],eul[M],dep[M];
int st[M][];
inline void Link(int x,int y){Next[++tot]=head[x]; to[tot]=y; head[x]=tot;}
inline void dfs(int x,int fat,int dd)
{
int i;
id[x]=++clk;
eul[clk]=x;
dep[clk]=dd;
for(i=head[x];i;i=Next[i]) if(to[i]!=fat)
{
dfs(to[i],x,dd+);
eul[++clk]=x;
dep[clk]=dd;
}
}
inline void pre(int n)
{
int i,j;
for(i=;i<=n;i++) st[i][]=i;
for(i=;i<=;i++)
{
for(j=;j<=n;j++)
{
int a=st[j][i-],b=st[j+(<<(i-))][i-];
if(dep[a]<dep[b]) st[j][i]=a;else st[j][i]=b;
}
}
}
inline int ask(int x,int y)
{
x=id[x]; y=id[y]; if(x>y) swap(x,y);
int oo=log2(y-x+);
int a=st[x][oo],b=st[y-(<<oo)+][oo];
if(dep[a]<dep[b]) return eul[a]; else return eul[b];
}
int main()
{
int i,x,y,z;
R(n); R(m);
for(i=;i<n;i++)
{
R(x); R(y); Link(x,y); Link(y,x);
}
dfs(,,);
pre(clk);
while(m--)
{
R(x); R(y); R(z);
int l1=ask(x,y),l2=ask(x,z),l3=ask(y,z),ll;
if(l1==l2) ll=l3;else if(l1==l3) ll=l2;else ll=l1;
W(ll); Wl(dep[id[x]]+dep[id[y]]+dep[id[z]]-dep[id[l1]]-dep[id[l2]]-dep[id[l3]]);
}
return ;
}
/*
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
output
5 2
2 5
4 1
6 0
*/

luogu4281的更多相关文章

  1. BZOJ1787/Luogu4281: [Ahoi2008]Meet 紧急集合

    画画图可知,三点\(lca\)必有两相同,\(a,b,c\)距离为\(dis_a + dis_b + dis_c - dis_{lca(a,b)} - dis_{lca(b,c)} - dis_{lc ...

随机推荐

  1. Spring Boot(一) 初步理解Spring Boot

    一.Spring Boot所解决的问题 Java开发十分笨重:繁多的配置.低下的开发效率.复杂的部署流程以头疼的第三方技术集成. Spring Boot的理念:习惯优于配置——项目中存在大量的配置,此 ...

  2. Iedis - Redis 在IDEA中的可视化工具破解

    2.如何破解 // 如果你没有改动IDEA的话,IDEA的插件库在这个目录下C:\Users\Administrator\.IntelliJIdea2017.3\config\plugins\Iedi ...

  3. 微信小程使用getCurrentPages函数操作父级数据

    微信小程使用getCurrentPages函数操作父级数据 let pages = getCurrentPages(); let prevPage = pages[pages.length - 2]; ...

  4. includes()函数的用法

    在ES5,Array已经提供了indexOf用来查找某个元素的位置,如果不存在就返回-1,但是这个函数在判断数组是否包含某个元素时有两个小不足,第一个是它会返回-1和元素的位置来表示是否包含,在定位方 ...

  5. 微信小程序data-传参

    <view bindtap="change" data-index="{{index}}">哈哈</view> change(event ...

  6. echarts —— 重叠图

    平时做堆叠图比较多,但是今天遇到一个要做重叠图的需求,记录一下~ 1.堆叠图,对应的 series: [] ,需要设置一个stack: "1",其中每个堆叠图的stack属性值都要 ...

  7. web开发中的Cookie与Session技术

    Cookie Cookie的由来 HTTP协议是无状态的,无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不会直接影响后 ...

  8. Django 开发相关知识 整理

    前言 前端ajax HTTP请求头 ajax上传文件 jsonp跨域 URL 设计 分发 url参数编码 反向生成url 视图 request对象 POST url信息 视图返回值 HttpRespo ...

  9. Java多线程(一)——线程基础和锁锁锁

    目录 Java多线程(一) 一.线程的定义 二.Synchronize线程同步 三.偏向锁.自旋锁.重量级锁 四.volatile关键字 五.Compare And Swap无锁自旋优化技术和ABA版 ...

  10. Codeforces 1216E2 枚举位数+二分

    两个二分 枚举位数 #include <bits/stdc++.h> #define MOD 1000000007 using namespace std; typedef long lo ...