Description

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

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

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

Input

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

Output

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

我天,这题恶心坏了.

话说没出样例就敢交题的我实在是tql。 ~w~

明显到\(LCA\)处就能取到最小的值。

会需要求到\(6\)种(貌似可以求的更少.

首先这六种情况怎么算出来的.

\[C_{3}^{2} \times 2 =6
\]

其中\(C_3^2\)代表在三个点中,随便选两个点求\(LCA\)记作\(X\)。

然后再求第三个点与\(X\)的\(LCA\)记作\(Y\)

注意,这里要选择\(X\)作为集合点.这样会更优.

因为走到\(Y\)的话就会是两个点对花费的贡献.这样明显更大啊.

而走到\(X\),这两个点对花费的贡献就会比较小了,另一个人多走就好了.

但是感觉不太对.但又的确是对的 emmm

比如这样:

  

简单来看的话,我们求出了\(b\)和\(c\)的\(LCA=X\)

\(a\)和\(X\)的\(LCA=Y\)

此时\(a,b,c\)走到\(X\)的价值为\(4\),走到\(Y\)的价值为\(5\)

(这只是一个小栗子啦 qwq)

代码

#include<cstdio>
#include<cctype>
#include<algorithm>
#define R register
#define N 500008
using namespace std;
inline void in(int &x)
{
int f=1;x=0;char s=getchar();
while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
while(isdigit(s)){x=x*10+s-'0';s=getchar();}
x*=f;
}
int head[N],tot,depth[N],dis[N];
int n,m,gw[N][21],f[N][21];
struct cod{int u,v;}edge[N<<2];
inline void add(int x,int y,int z)
{
edge[++tot].u=head[x];
edge[tot].v=y;
head[x]=tot;
}
void dfs(int u,int fa)
{
f[u][0]=fa;depth[u]=depth[fa]+1;
dis[u]=dis[fa]+1;
for(R int i=1;(1<<i)<=depth[u];i++)
f[u][i]=f[f[u][i-1]][i-1];
for(R int i=head[u];i;i=edge[i].u)
{
if(edge[i].v==fa)continue;
dfs(edge[i].v,u);
}
}
inline int lca(int x,int y)
{
if(depth[x]>depth[y])swap(x,y);
for(R int i=17;i>=0;i--)
if(depth[x]+(1<<i)<=depth[y])
y=f[y][i];
if(x==y)return y;
for(R int i=17;i>=0;i--)
{
if(f[x][i]==f[y][i])continue;
x=f[x][i],y=f[y][i];
}
return f[x][0];
}
int main()
{
in(n),in(m);
for(R int i=1,x,y;i<n;i++)
in(x),in(y),add(x,y,1),add(y,x,1);
dfs(1,0);
for(R int i=1,x,y,z;i<=m;i++)
{
in(x),in(y),in(z);
R int a=lca(x,y),b=lca(x,z),c=lca(y,z);
R int aa=lca(a,z),bb=lca(y,b),cc=lca(x,c);
R int father,res=214748364;
int ansa=dis[x]+dis[y]-2*dis[a]+dis[a]-2*dis[aa]+dis[z];
int ansb=dis[x]+dis[z]-2*dis[b]+dis[b]-2*dis[bb]+dis[y];
int ansc=dis[y]+dis[z]-2*dis[c]+dis[c]-2*dis[cc]+dis[x];
if(res>ansa)res=ansa,father=a;
if(res>ansb)res=ansb,father=b;
if(res>ansc)res=ansc,father=c;
printf("%d %d\n",father,res);
}
}

LCA【p4281】[AHOI2008]紧急集合 / 聚会的更多相关文章

  1. P4281 [AHOI2008]紧急集合 / 聚会

    P4281 [AHOI2008]紧急集合 / 聚会 lca 题意:求3个点的lca,以及3个点与lca的距离之和. 性质:设点q1,q2,q3 两点之间的lca t1=lca(q1,q2) t2=lc ...

  2. P4281 [AHOI2008]紧急集合 / 聚会[LCA]

    解析 蒟蒻用的办法比较蠢,不如上面的各位大佬,直接化成一个式子了,我还是分类讨论做的. 下面正文. 猜想:最优集合点一定是三点任意两对点对应的路径的交点. 不妨这样想,如果任意两个人经过同一条路径,那 ...

  3. LUOGU P4281 [AHOI2008]紧急集合 / 聚会 (lca)

    传送门 解题思路 可以通过手玩或打表发现,其实要选的点一定是他们三个两两配对后其中一对的$lca$上,那么就直接算出来所有的$lca$,比较大小就行了. #include<iostream> ...

  4. [AHOI2008]紧急集合 / 聚会(LCA)

    [AHOI2008]紧急集合 / 聚会 题目描述 欢乐岛上有个非常好玩的游戏,叫做"紧急集合".在岛上分散有N个等待点,有N-1条道路连接着它们,每一条道路都连接某两个等待点,且通 ...

  5. 【题解】洛谷P4281 [AHOI2008] 紧急集合(求三个点LCA)

    洛谷P4281:https://www.luogu.org/problemnew/show/P4281 思路 答案所在的点必定是三个人所在点之间路径上的一点 本蒟蒻一开始的想法是:先求出2个点之间的L ...

  6. [AHOI2008]紧急集合 / 聚会

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

  7. Luogu 4281 [AHOI2008]紧急集合 / 聚会

    BZOJ 1832 写起来很放松的题. 首先发现三个点在树上一共只有$3$种形态,大概长这样: 这种情况下显然走到三个点的$lca$最优. 这种情况下走到中间那个点最优. 这种情况下走到$2$最优. ...

  8. 洛谷 P4281 [AHOI2008] 紧急集合 题解

    挺好的一道题,本身不难,就把求两个点的LCA变为求三个点两两求LCA,不重合的点才是最优解.值得一提的是,最后对答案的处理运用差分的思想:假设两点 一点深度为d1,另一点 深度为d2,它们LCA深度为 ...

  9. 「AHOI2008」「LuoguP4281」紧急集合 / 聚会(LCA

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

随机推荐

  1. Python SimpleHTTPServer简单HTTP服务器

    搭建FTP,或者是搭建网络文件系统,这些方法都能够实现Linux的目录共享.但是FTP和网络文件系统的功能都过于强大,因此它们都有一些不够方便的地方.比如你想快速共享Linux系统的某个目录给整个项目 ...

  2. shell之echo and printf

    #!/bin/sh _________echo___________#read name #echo "$name It is a test" #read命令从标准的输入中读取一行 ...

  3. Oracle 自增写给自己的

    首先咱先建一张表: CREATE TABLE example( ID Number(4) NOT NULL PRIMARY KEY, NAME VARCHAR(25), PHONE VARCHAR(1 ...

  4. HTML5 FileReader接口学习笔记

    1.FileReader概述 FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据. 其中F ...

  5. html span和div的区别

    div与span区别及用法 div与span区别及用法 DIV与SPAN区别及div与san用法篇 接下来了解在div+css开发的时候在html网页制作,特别是标签运用中div和span的区别及用法 ...

  6. 爬虫:Scrapy14 - Telnet 终端(Telnet Console)

    Scrapy 提供了内置的 Telnet 终端,以供检查,控制 Scrapy 运行的进程.Telnet 仅仅是一个运行在 Scrapy 进程中的普通 Python 终端.因此你可以在其中做任何是. T ...

  7. Horn–Schunck 光流法与其算法理解(gup cuda)

    1. 基于Horn-Schunck模型的光流算法 1.1     光流的约束条件 光流 的假设条件认为图像序列,在时间t 的某一像素点与在时间t+1的这一像素点的偏移量保持不变,即 .这就是灰度值守恒 ...

  8. java 计算精度处理

    1.设计思想: 定义两个字符串number1和number2,分别输入一串数字,然后定义两个BigDecimal类的对象f1,f2分别接收number1和number2的值,然后调用BigDecima ...

  9. 【bzoj3829】[Poi2014]FarmCraft 贪心

    原文地址:http://www.cnblogs.com/GXZlegend/p/6826667.html 题目描述 In a village called Byteville, there are   ...

  10. BZOJ1025 [SCOI2009]游戏 【置换群 + 背包dp】

    题目链接 BZOJ1025 题解 题意就是问一个\(1....n\)的排列在同一个置换不断重复下回到\(1...n\)可能需要的次数的个数 和置换群也没太大关系 我们只需知道同一个置换不断重复,实际上 ...