解析

蒟蒻用的办法比较蠢,不如上面的各位大佬,直接化成一个式子了,我还是分类讨论做的。

下面正文。

猜想:最优集合点一定是三点任意两对点对应的路径的交点。

不妨这样想,如果任意两个人经过同一条路径,那么就要支付双倍的价钱,为了使支付的钱最少,我们就要使得这种情况出现的最少。由于图是一颗树,如果选择三点交点,一定不会出现这样的边。

那么如何求交点呢?

可以分成两种情况:

1、三个点都在以某个点为根的子树中。

2、有两个点在以某个点为根的子树,另一个点在它上面。

判断比较麻烦,由于无法知道三点确切的相对位置关系,所以这就导致情况2分出来好几种判断法则。实际上它们本质是一样的。

参考代码

吸氧最优解第二页,不吸氧掉到最后一页去了(摊。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<vector>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 500010
#define MOD 2520
#define E 1e-12
using namespace std;
inline int read()
{
int f=1,x=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
struct rec{
int next,ver;
}g[N<<1];
int head[N],tot,n,m;
inline void add(int x,int y)
{
g[++tot].ver=y;
g[tot].next=head[x],head[x]=tot;
}
int size[N],top[N],son[N],fa[N],dep[N],id[N],cnt;
inline void dfs1(int x,int f,int deep)
{
size[x]=1,fa[x]=f,dep[x]=deep;
int maxson=-1;
for(int i=head[x];i;i=g[i].next){
int y=g[i].ver;
if(y==f) continue;
dfs1(y,x,deep+1);
size[x]+=size[y];
if(maxson<size[y]) maxson=size[y],son[x]=y;
}
}
inline void dfs2(int x,int topf)
{
id[x]=++cnt,top[x]=topf;
if(!son[x]) return;
dfs2(son[x],topf);
for(int i=head[x];i;i=g[i].next){
int y=g[i].ver;
if(y==fa[x]||y==son[x]) continue;
dfs2(y,y);
}
}
inline int lca(int x,int y)
{
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
return x;
}
inline int dist(int x,int y){return dep[x]+dep[y]-2*dep[lca(x,y)];}//两点距离
int main()
{
n=read(),m=read();
for(int i=1;i<n;++i){
int u=read(),v=read();
add(u,v),add(v,u);
}
dfs1(1,0,1);dfs2(1,1);//树剖LCA
while(m--){
int x=read(),y=read(),z=read();
int k1=lca(x,y),k2=lca(y,z),k3=lca(x,z);//f**k lca
if(k1==k2&&k2==k3)//case 1
printf("%d %d\n",k1,dep[x]+dep[y]+dep[z]-3*dep[k1]);
else if(k1!=k2&&k2!=k3&&k1==k3)
printf("%d %d\n",k2,dist(k2,x)+dist(y,z));
else if(k1!=k3&&k3!=k2&&k1==k2)
printf("%d %d\n",k3,dist(k3,y)+dist(x,z));
else if(k2!=k1&&k1!=k3&&k2==k3)//case 2
printf("%d %d\n",k1,dist(k1,z)+dist(x,y));
}
return 0;
}

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

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

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

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

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

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

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

  4. LCA【p4281】[AHOI2008]紧急集合 / 聚会

    Description 欢乐岛上有个非常好玩的游戏,叫做"紧急集合".在岛上分散有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. 统计numpy数组中每个值出现的个数

    统计numpy数组中某一个值或某几个值出现的个数:sum(data==4) # 统计出现了几个cluster include0Cluster = sum(res == 0) include1Clust ...

  2. Maven 教程(7)— Maven使用的最佳实践

    原文地址:https://blog.csdn.net/liupeifeng3514/article/details/79544201 1.设置MAVEN_OPTS环境变量 通常需要设置MAVEN_OP ...

  3. ThreadPoolExecutor源码2

    public class ThreadPoolExecutor1 extends AbstractExecutorService1 { // 11100000000000000000000000000 ...

  4. SQL Server创建、更改和删除架构

    SQL Server创建架构 学习如何使用SQL Server CREATE SCHEMA在当前数据库中创建新架构. SQL Server中的架构是什么 架构是包括表,视图,触发器,存储过程,索引等在 ...

  5. Lab_1:练习5——实现函数调用堆栈跟踪函数

    题目:实现函数调用堆栈跟踪函数 我们需要在lab1中完成kdebug.c中函数print_stackframe的实现,可以通过函数print_stackframe来跟踪函数调用堆栈中记录的返回地址.如 ...

  6. Docker 下的Zookeeper以及.ne core 的分布式锁

    单节点 1.拉取镜像:docker pull zookeeper 2.运行容器 a.我的容器同一放在/root/docker下面,然后创建相应的目录和文件, mkdir zookeeper cd zo ...

  7. Java学习:static 关键字概述

    static 关键字概述 一旦用了static关键字,那么这样的内容不再属于对象自己.而是属于类的,所以凡是本类的对象,都共享同一份. 如果没有static关键字,那么必须首先创建对象,然后通过对象才 ...

  8. sqlserver获得数据库非聚集索引的代码

    创建Index DECLARE @zindex_sql NVARCHAR(max); SET @zindex_sql = N''; SELECT @zindex_sql = @zindex_sql + ...

  9. Linux学习笔记之iptables学习笔记

    iptables系列学习推荐: http://www.zsythink.net/archives/category/%e8%bf%90%e7%bb%b4%e7%9b%b8%e5%85%b3/iptab ...

  10. asp.net core 系列之允许跨域访问2之测试跨域(Enable Cross-Origin Requests:CORS)

    这一节主要讲如何测试跨域问题 你可以直接在官网下载示例代码,也可以自己写,我这里直接使用官网样例进行演示 样例代码下载: Cors 一.提供服务方,这里使用的是API 1.创建一个API项目.或者直接 ...