题目描述

欢乐岛上有个非常好玩的游戏,叫做“紧急集合”。在岛上分散有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


题解

对于每次询问,设三个点分别为x1,x2,x3。

两两求lca,得到三个lca,其中最深的那个点为最优集合点。

不会严谨证明,画画图感性理解还是不难的。

然后有了集合点,问题转化为求树上两点间的距离。

随便搞搞就出来了。

 /*
qwerta
P4281 [AHOI2008]紧急集合 / 聚会
Accepted
100
代码 C++,2.24KB
提交时间 2018-10-09 18:50:02
耗时/内存
1148ms, 24100KB
*/
#include<iostream>
#include<cstdio>
using namespace std;
inline int read()
{
char ch=getchar();
int x=;
while(!isdigit(ch))ch=getchar();
while(isdigit(ch)){x=x*+ch-'';ch=getchar();}
return x;
}
const int MAXN=;
struct emm{
int e,f;
}a[*MAXN];
int h[MAXN];
int fa[MAXN],top[MAXN],d[MAXN],siz[MAXN],z[MAXN];
void dfs(int x)
{
siz[x]=,top[x]=x;
int mac=,macc=;
for(int i=h[x];i;i=a[i].f)
if(!d[a[i].e])
{
d[a[i].e]=d[x]+;
fa[a[i].e]=x;
dfs(a[i].e);
siz[x]+=siz[a[i].e];
if(siz[a[i].e]>macc){mac=a[i].e,macc=siz[a[i].e];}
}
z[x]=mac,top[mac]=x;
return;
}
int q[MAXN],dfn[MAXN];
int tot=;
void dfss(int x)
{
q[++tot]=x;
dfn[x]=tot;
if(z[x])dfss(z[x]);
for(int i=h[x];i;i=a[i].f)
if(fa[a[i].e]==x&&a[i].e!=z[x])
dfss(a[i].e);
return;
}
int fitop(int x)
{
if(top[x]==x)return x;
return top[x]=fitop(top[x]);
}
int lca(int u,int v)//树剖求lca
{
while(top[u]!=top[v])
{
if(d[top[u]]<d[top[v]])swap(u,v);
u=fa[top[u]];
}
if(d[u]<d[v])swap(u,v);
return v;
}
int dmin(int x1,int x2,int x3)//找深度最深的点
{
if(d[x1]>=d[x2]&&d[x1]>=d[x3])return x1;
if(d[x2]>=d[x1]&&d[x2]>=d[x3])return x2;
return x3;
}
int dis(int u,int v)//求距离
{
int ans=;
while(top[u]!=top[v])
{
if(d[top[u]]<d[top[v]])swap(u,v);
ans+=dfn[u]-dfn[top[u]]+;
u=fa[top[u]];
}
if(d[u]<d[v])swap(u,v);
ans+=dfn[u]-dfn[v];
return ans;
}
void write(int x)
{
if(x>)write(x/);
putchar(x%+'');
return;
}
int main()
{
//freopen("a.in","r",stdin);
int n=read(),m=read();
tot=;
for(int i=;i<n;++i)
{
int u=read(),v=read();
a[++tot].f=h[u];
h[u]=tot;
a[tot].e=v;
a[++tot].f=h[v];
h[v]=tot;
a[tot].e=u;
}
int s=min(n,);//幸运数赛高!(逃
d[s]=;
dfs(s);
tot=;
dfss(s);
for(int i=;i<=n;++i)
top[i]=fitop(i);
for(int i=;i<=m;++i)
{
int x1=read(),x2=read(),x3=read();
int l1=lca(x1,x2),l2=lca(x2,x3),l3=lca(x1,x3);//两两取lca
int p=dmin(l1,l2,l3);//取最深的为集合点
int ans=dis(x1,p)+dis(x2,p)+dis(x3,p);//算距离,加起来
write(p);
putchar(' ');
write(ans);
putchar('\n');//输出
}
return ;
}

「AHOI2008」「LuoguP4281」紧急集合 / 聚会(LCA的更多相关文章

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

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

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

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

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

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

  4. 众安「尊享e生」果真牛的不可一世么?

    近日,具有互联网基因的.亏损大户(成立三年基本没盈利,今年二季度末亏损近4亿,你能指望它多厉害?).财产险公司—众安推出“尊享e生”中高端医疗保险(财险公司经营中高端医疗真的很厉害?真的是中高端医疗险 ...

  5. XCActionBar 「Xcode 中的 Alfred」

    下载地址:https://github.com/pdcgomes/XCActionBar 基本命令: (1)「command+shift+8」或者双击「command」键可以打开「动作输入框窗口」 ( ...

  6. Git 执行 「fork 出来的仓库」和「最新版本的原仓库」内容同步更新

    当我们在 GitHub 上 fork 出一个仓库后,如果原仓库更新了,此时怎样才能保证我们 fork 出来的仓库和原仓库内容一致呢?我们一般关注的是仓库的 master(主干分支)的内容,通过以下步骤 ...

  7. 【翻译】西川善司的「实验做出的游戏图形」「GUILTY GEAR Xrd -SIGN-」中实现的「纯卡通动画的实时3D图形」的秘密,后篇

    http://www.4gamer.net/games/216/G021678/20140714079/     连载第2回的本回,  Arc System Works开发的格斗游戏「GUILTY G ...

  8. 翻译「C++ Rvalue References Explained」C++右值引用详解 Part1:概述

    本文系对「C++ Rvalue References Explained」 该文的翻译,原文作者:Thomas Becker. 该文较详细的解释了C++11右值引用的作用和出现的意义,也同时被Scot ...

  9. 「Windows MFC 」「Edit Control」 控件

    「Windows MFC 」「Edit Control」 控件

随机推荐

  1. Please configure Spring facet or use 'Create Default Context' to add one including all unmapped files.

    有时候我们刚进入 Intellij IDEA时会出现这样一个情况,原因是IDEA没有找到spring的配置文件,我们需要添加spring文件给idea管理 参考: 1.https://www.jetb ...

  2. c++程序猿经典面试题(2)

    1.以下程序的输出结果是? #include<stdio.h> main(){ int b=3; int arr[]={6,7,8,9,10}; int *ptr=arr; *(ptr++ ...

  3. Go语言阅读小笔记,来自知呼达达关于unsafe.Pointer的分享.

    第一式 - 获得Slice和String的内存数据 func stringPointer(s string) unsafe.Pointer { p := (*reflect.StringHeader) ...

  4. sass的使用(载)

    一.什么是SASSSASS是一种CSS的开发工具,提供了许多便利的写法,大大节省了设计者的时间,使得CSS的开发,变得简单和可维护.本文总结了SASS的主要用法.我的目标是,有了这篇文章,日常的一般使 ...

  5. vs2012编译ffmpeg

    从官方网站down下来的ffmpeg没有pdb文件不方便调试,为此使用VS2012编译ffmpeg. 编译步骤: 一.安装MinGW,具体的安装方法上一篇文章已经有介绍这里不在赘述. 二.下载文件并放 ...

  6. QQ空间g_tk、bkn加密参数算法

    g_tk是腾讯在QQ空间这一领域使用的密文,有写数据包或者url参数中需要加入你计算出的g_tk才能成功! 下面是通过浏览器抓包工具抓取 访问该js内容找出 QZONE.FrontPage.getAC ...

  7. TNS-01201: Listener cannot find executablen 错误

    近期在启动监听器的时候收到了TNS-01201: Listener cannot find executable...的错误提示.这个错误还真是一个一直没有碰到过的错误.咋一看还真不明确是怎么一回事呢 ...

  8. Integrate NSX into Neutron

    NSX is VMware's strategy for Software-defined networking, it was implemented purely in software, and ...

  9. 关于erlang中的timer:tc/3

    timer:tc/3对于统计函数运行时间是个很不错的函数, 截图timer:tc/1,tc/2,tc/3的API: 拿斐波那契数列入手做个讲解: -module(fib). -export([fib/ ...

  10. EF架构~终于自己架构了一个相对完整的EF方案

    EF4.1学了有段时间了,没有静下来好好研究它的架构,今天有空正好把它的架构及数据操作这段拿出来,希望给大家带来帮助,对我自己也是一种总结:P 从图中可以看到,我们用的是MVC3进行程序开发的,哈哈, ...