当前位置: 首页 > 编程日记 > 正文

[Ahoi2008]Meet 紧急集合

1787: [Ahoi2008]Meet 紧急集合

Time Limit: 20 Sec  Memory Limit: 162 MB
http://www.lydsy.com/JudgeOnline/problem.php?id=1787

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

Source

Day1

结论1:集合点一定在某两个点的lca上

结论2: 3个点两两算出lca,至少有2个lca相同

结论3:不同的那个lca(或3个都相同的lca)就是集合点,3个点到这个点的总距离最小

证明1:如图所示,假设等待点是 3、5、10

3个点之间的路径用蓝色标注,其余路径用橙色标注

要证明结论1,可以证明以下几点:

① 集合点 选在蓝色路径上的点 一定比 选在橙色路径上的点 更优

    证明:如果集合点选在橙色路径上,即三个点可以不经过集合点到达其他点,那么选橙色路径顶端的蓝色路径上一点会更优

    例如 上图中 8号点要比13号点 更优

② 集合点若选的不是lca,那么集合点越靠近lca,越优。

   我们假设选的点

   证明:设点a,b,c,lca为a和b的lca,设选的点d不是lca,d往lca方向移动一点,设这一点为e

           那么由d向e的过程,会使①2个点的路径长度-1,另外1个点的路径长度+1   或者② 3个点的路径长度各-1

  例子:①在上图中选3、5、10,集合点由4向2转移   ②在上图中好像没有。。。画一个三叉树,集合点由上往下移即可

综上可证结论1

有了结论1,就可以做这个题了,3个lca挨着算一遍即可

结论2关键点:点向上的路径有且只有唯一的一条

结论3关键点:相同的那个lca一定在另一个lca的上面

这样就可以只算那一个lca即可

然后,剩下的难以描述(语文不好),画图意会吧...

代码一:算3个lca && 倍增求lca  && 读入优化    结果:上图第3行

#include<algorithm>
#include<cstdio>
#include<cmath>
#define N 500001
using namespace std;
int n,m,id[N],cnt,fa[N][21],p,deep[N],tmp;
int front[N],next[N*2],to[N*2],tot;
int lca1,lca2,lca3;
int read()
{int x=0; char c=getchar();while(c<'0'||c>'9') c=getchar();while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar();}return x;
}
void add(int x,int y)
{to[++tot]=y; next[tot]=front[x]; front[x]=tot;to[++tot]=x; next[tot]=front[y]; front[y]=tot;
}
void dfs(int x)
{id[x]=++cnt;for(int i=front[x];i;i=next[i])if(to[i]!=fa[x][0]) {fa[to[i]][0]=x;deep[to[i]]=deep[x]+1;dfs(to[i]);}
}
int lca(int x,int y)
{if(x==y) return x;if(id[x]<id[y]) swap(x,y);for(int i=p;i>=0;i--)if(id[fa[x][i]]>id[y])x=fa[x][i];return fa[x][0];
}
int dis(int x,int y)
{int lc=lca(x,y);return deep[x]+deep[y]-2*deep[lc];
}
int main()
{n=read(); m=read();int x,y,z;for(int i=1;i<n;i++){x=read(); y=read();add(x,y);}dfs(1);p=log(n)/log(2)+1;for(int j=1;j<=p;j++)for(int i=1;i<=n;i++)fa[i][j]=fa[fa[i][j-1]][j-1];int ans1,ans2,tmp;while(m--){x=read(); y=read(); z=read();lca1=lca(x,y); lca2=lca(x,z); lca3=lca(y,z);ans1=lca1; ans2=dis(x,lca1)+dis(y,lca1)+dis(z,lca1);tmp=dis(x,lca2)+dis(y,lca2)+dis(z,lca2);if(tmp<ans2) {ans2=tmp;ans1=lca2;}tmp=dis(x,lca3)+dis(y,lca3)+dis(z,lca3);if(tmp<ans2){ans2=tmp;ans1=lca3;}printf("%d %d\n",ans1,ans2);}
}
View Code

代码二:算1个lca && 倍增求lca   && 读入优化   结果: 上图第2行

#include<algorithm>
#include<cstdio>
#include<cmath>
#define N 500001
using namespace std;
int n,m,id[N],cnt,fa[N][21],p,deep[N],tmp,ans2;
int front[N],next[N*2],to[N*2],tot;
int lca1,lca2,lca3;
int read()
{int x=0; char c=getchar();while(c<'0'||c>'9') c=getchar();while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar();}return x;
}
void add(int x,int y)
{to[++tot]=y; next[tot]=front[x]; front[x]=tot;to[++tot]=x; next[tot]=front[y]; front[y]=tot;
}
void dfs(int x)
{id[x]=++cnt;for(int i=front[x];i;i=next[i])if(to[i]!=fa[x][0]) {fa[to[i]][0]=x;deep[to[i]]=deep[x]+1;dfs(to[i]);}
}
int lca(int x,int y)
{if(x==y) return x;if(id[x]<id[y]) swap(x,y);for(int i=p;i>=0;i--)if(id[fa[x][i]]>id[y])x=fa[x][i];return fa[x][0];
}
int dis(int x,int y)
{int lc=lca(x,y);return deep[x]+deep[y]-2*deep[lc];
}
int main()
{n=read(); m=read();int x,y,z;for(int i=1;i<n;i++){x=read(); y=read();add(x,y);}dfs(1);p=log(n)/log(2)+1;for(int j=1;j<=p;j++)for(int i=1;i<=n;i++)fa[i][j]=fa[fa[i][j-1]][j-1];while(m--){x=read(); y=read(); z=read();lca1=lca(x,y); lca2=lca(x,z); lca3=lca(y,z);if(lca1==lca2) tmp=lca3;else if(lca1==lca3) tmp=lca2;else tmp=lca1;ans2=dis(x,tmp)+dis(y,tmp)+dis(z,tmp);printf("%d %d\n",tmp,ans2);}
}
View Code

代码三:算1个lca && 树链剖分求lca && 读入优化  结果:上图第1行

#include<algorithm>
#include<cstdio>
#include<cmath>
#define N 500001
using namespace std;
int n,m,tmp,ans;
int front[N],next[N*2],to[N*2],tot;
int lca1,lca2,lca3;
int son[N],deep[N],bl[N],fa[N];
int read()
{int x=0; char c=getchar();while(c<'0'||c>'9') c=getchar();while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar();}return x;
}
void add(int x,int y)
{to[++tot]=y; next[tot]=front[x]; front[x]=tot;to[++tot]=x; next[tot]=front[y]; front[y]=tot;
}
void dfs1(int x)
{son[x]++;for(int i=front[x];i;i=next[i])if(to[i]!=fa[x]) {fa[to[i]]=x;deep[to[i]]=deep[x]+1;dfs1(to[i]);son[x]+=son[to[i]];}
}
void dfs2(int x,int top)
{bl[x]=top;int y=0;for(int i=front[x];i;i=next[i])if(to[i]!=fa[x]&&son[to[i]]>son[y]) y=to[i];if(!y) return;dfs2(y,top);for(int i=front[x];i;i=next[i])if(to[i]!=fa[x]&&to[i]!=y) dfs2(to[i],to[i]); 
}
int lca(int x,int y)
{while(bl[x]!=bl[y]){if(deep[bl[x]]<deep[bl[y]]) swap(x,y);x=fa[bl[x]];}return deep[x]<deep[y] ? x:y;
}
int dis(int x,int y)
{int lc=lca(x,y);return deep[x]+deep[y]-2*deep[lc];
}
int main()
{n=read(); m=read();int x,y,z;for(int i=1;i<n;i++){x=read(); y=read();add(x,y);}dfs1(1);dfs2(1,1);while(m--){x=read(); y=read(); z=read();lca1=lca(x,y); lca2=lca(x,z); lca3=lca(y,z);if(lca1==lca2) tmp=lca3;else if(lca1==lca3) tmp=lca2;else tmp=lca1;ans=dis(x,tmp)+dis(y,tmp)+dis(z,tmp);printf("%d %d\n",tmp,ans);}
}
View Code

上图第4行为 算3个lca && 倍增求lca  

转载于:https://www.cnblogs.com/TheRoadToTheGold/p/6822268.html

相关文章:

C++ 回调函数

函数指针 函数指针是一种指针&#xff0c;具体来说是&#xff1a;指向函数入口地址的指针。 #include <iostream> using namespace std; double function_t(int val) {return val; } int main() {double (*ptr)(int); // 创建一个函数指针&#xff0c;返回值为doubl…

想知道什么是“成员变量”吗?

成员变量是直接定义在“类”中的量&#xff1b; 特点&#xff1a;成员变量有默认值,具体请看表格 数据类型默认值整型0浮点型0.0char’ ’booleanfalse其他类型null 成员变量的作用就是可以详细描述对象信息 我们来举个例子&#xff1a; public class UserInfo{int age;doubl…

Linux09-网络配置

目录 一、网络配置基础 1.1、网络接口 1.2、设置主机名 二、nmcli配置网络 2.1、配置固定的IP地址等 2.2、连接wifi 三、链路聚合等 一、网络配置基础 1.1、网络接口 先来对比一下RHEL6、RHEL7关于网络接口上的一些差别。 RHEL6 RHEL7 配置文件位置 /etc/sysconfig…

VScode配置ROS环境

创建一个文件夹 使用catkin_make编译工作空间的根目录 使用VScode打开 VScode 中编译 ros 快捷键 ctrl shift B 调用编译&#xff0c;选择:catkin_make:build 可以点击配置&#xff08;右边的小齿轮&#xff09;&#xff0c;修改.vscode/tasks.json 文件 { // 有关 tasks.j…

从Excel中导入数据时,提示“未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序”的解决办法...

注意&#xff0c;64位系统&#xff0c;用64位的补丁文件; https://www.cnblogs.com/A2008A/articles/2438962.html 操作系统&#xff1a;使用的是64位的Windows Server 2008 解决办法&#xff1a; 这是由于该计算机上没有安装Microsoft Access数据库引擎组件&#xff0c;该组件…

天兔(Lepus)监控系统慢查询分析平台安装配置

转http://suifu.blog.51cto.com/9167728/1770672 被监控端要安装pt工具 1234[rootHE1~]## yum -y install perl-IO-Socket-SSL[rootHE1~]## yum -y install perl-DBI[rootHE1~]## yum -y install perl-DBD-MySQL[rootHE1~]## yum -y install perl-Time-HiRes[rootHE1~]# tar xv…

五分钟让你搞懂什么是“构造方法”

构造方法的形式&#xff1a;类名([参数列表]){} 特点&#xff1a;- 构造方法没有返回值&#xff0c;就算void也不能有&#xff0c;这点与Java方法(或叫函数)不一样&#xff1b;- 一个类中默认无参构造方法&#xff0c;但是当定义了一个有参构造方法时&#xff0c;则默认无参构造…

Linux10-归档、系统间复制文件

目录 一、tar命令 二、scp、sftp命令 三、rsync命令 一、tar命令 tar命令可以归档文件、目录&#xff0c;提取创建的归档文件&#xff0c;同时进行压缩解压缩。使用tar选项时不需要加-&#xff0c;下面是常用的tar选项。 c&#xff0c;创建一个存档。x&#xff0c;提取一个…

pattern

常用的正则表达式 0-9 pattern"[0-9]*" 信用卡 [0-9]{13,16} 银联卡 ^62[0-5]\d{13,16}$ Visa: ^4[0-9]{12}(?:[0-9]{3})?$ 万事达&#xff1a;^5[1-5][0-9]{14}$ QQ号码&#xff1a; [1-9][0-9]{4,14} 手机号码&#xff1a;^(13[0-9]|14[5|7]|15[0|1|2|3|5…

VScode配置CMAKE文件

创建一个vscode文件 记得一定要创建一个build文件夹&#xff0c;因为cmake编译过程中产生的中间文件会放到build文件夹中。 打开VScode 配置文件 launch.json {"version": "0.2.0","configurations": [{"name": "(gdb) Launc…

三分钟了解“Java重写”

要了解“Java重写”&#xff0c;首先要知道“继承”&#xff0c;继承是一种基于已有类&#xff08;父类&#xff09;创建新类&#xff08;子类&#xff09;的一种方式 下面的Son类继承了Father类 public class Father(){public void eat(String name,int age){System.out.prin…

2017 .NET 開發者須知

筆記&#xff0d;Scott Hanselman 的 2017 .NET 開發者須知 转载http://blog.darkthread.net/post-2017-01-16-dotnet-dev-should-know-2017.aspx Scott Hanselman 前兩天有篇文章&#xff0d;What .NET Developers ought to know to start in 2017&#xff0c;我的工作&#x…

Linux11-RPM软件包和YUM源

目录 一、rpm 二、yum 一、rpm 红帽开发了RPM软件包管理器&#xff0c;RPMRedhat Package Manager。RPM软件包名的格式为<name>-<version>-<release>.<arch>.rpm。比如&#xff0c;httpd-tools-2.4.6-7.el7.x86_64.rpm&#xff0c;其中namehttpd-to…

SQL Server 与 ORACLE 的区别

sql server 与 oracle的区别&#xff1a; DBMS 数据库管理系统 1.数据类型不同。 sql server 的数据类型&#xff1a;int ,smallint ,char,varchar,nchar,nvarchar,ntext,datetime,smalldatetime,money,decima, float,bit…… oracle 的数据类型&#xff1a;number(…

php如何定时执行任务

PHP的实现决定了它没有Java和.Net这种AppServer的概念, 而http协议是一个无状态的协议, php只能被用户触发, 被调用, 调用后会自动退出内存, 没有常驻内存, 就没有办法准确的定时处理那么, 如果需要用PHP定时执行某些任务的话, 可以有以下俩个方法&#xff0c;下面就让我们来看…

Java的多态(详尽版)

父类类型&#xff08;比如Mammal&#xff09;的变量指向子类&#xff08;比如Cat&#xff09;创建的对象&#xff0c;使用该变量调用父类中一个*被子类重写*的方法&#xff08;比如move方法&#xff09;&#xff0c; 则父类中的方法呈现出不同的行为特征&#xff0c;这就是多态…

C++ memset

memset的主要功能是对一片内存进行赋值&#xff08;逐字节进行&#xff09; 包含在头文件#include < cstring >中。 函数模板 void *memset(void *s, int v, size_t n); s&#xff1a;数组名&#xff0c;或指向某一片内存的指针名&#xff0c; v&#xff1a;要填充的值…

Linux12-文件系统基础

目录 一、识别文件系统和设备 1.1、分区 1.2、逻辑卷 二、挂载卸载文件系统命令mount、umount、blkid、lsof 2.1、挂载 2.2、卸载 三、检查文件系统命令df、du 四、制作文件链接命令ln 4.1、硬链接 4.2、软连接 五、查找文件命令locate、find 一、识别文件系统和设备…

C语言------运算符和表达式

1. 自动类型转换是由计算机自动完成的&#xff0c;当由低级别的向高级别的转换时&#xff0c;不会报警&#xff0c;但是当高级别的向低级别的转换时&#xff0c;会发出告警信息&#xff0c;信息意思就是提示会有部分数据丢失的可能。 2. 强制类型转换是通过“&#xff08;数据类…

String类常用方法(看一眼就懂)

public class Test{public static void main(String[] args){String name " T o m ";System.out.println(name.length()); //输入字符的长度&#xff0c;&#xff08;空格也占一个字节&#xff09;System.out.println(name.equals(" T o m ")); //判断连…

1.2.2一个数可以有多少种用连续素数之和表示

#include <iostream> using namespace std; const int maxp2000,n10000; int prime[maxp],total0; bool isprime(int k)//bool函数用来求素数 {for(int i0;i<total;i)if(k%prime[i]0)//判断素数的一种方法&#xff08;用这个数对数组当中所有的 素数 进行取余&#xf…

C++查找算法(更新中)

C的查找分为静态查找与动态查找。 静态查找&#xff1a;只是在查找表中判断是否有这一个元素&#xff0c;取出这个元素的属性。 动态查找&#xff1a;在查找过程中&#xff0c;会对查找表做出修改。 比如插入、删除。 静态查找 静态查找包括&#xff1a;顺序查找、二分查找、…

编译Linux Kernel(linux-4.19.178)并制作成rpm文件

目录 一、安装依赖项 二、下载、解压缩、制作.config文件 三、编译内核及打包 四、升级内核 首次尝试编译Linux内核&#xff0c;记录过程&#xff0c;提供Linux Kernel(linux-4.19.178)下载https://download.csdn.net/download/qpeity/15637656。 一、安装依赖项 安装依赖…

2016 多校赛3 A 水 B 期望,规律 C 各种博弈 J 物理题,积分 K 暴力,水

2016 Multi-University Training Contest 3 A - Sqrt Bo 题意&#xff1a;给一个数 n&#xff0c;问n要多少次平方后化为1&#xff0c;如果超过5次输出"TAT"。 tags&#xff1a;SB题&#xff0c;5次内平方的&#xff0c;即小于2*2*4*16*256*65536 。然后0、1特判。 #…

BZOJ 1801 [Ahoi2009]中国象棋(线性动规)(洛谷P2051)

题意&#xff1a;就是在n*m的格子中放“炮”&#xff08;中国象棋中的棋子&#xff09;问有多少种放法&#xff0c;使得没有任意的两个炮相互攻击 思路&#xff1a;我们很容易的得到一列或者一行中最多放下两个炮&#xff08;我也只能得到这些了&#xff0c;满脑子状压&#xf…

Java中父类构造方法对子类构造方法的影响(不是一句话可以说清的)

推荐的阅读顺序是&#xff1a;先看Test类&#xff0c;再根据提示看父类和子类 让我们通过代码来了解一下&#xff1a;创建一个父类&#xff1a; public class Father{public Father(){super();//默认调用Object构造方法(Object是所有类的父类)System.out.println("父类构…

ORB_SLAM2概述

追踪线程 灰度化处理。构建当前帧&#xff08;提取每幅图像的特征点&#xff0c;并分配到网格中&#xff0c;这会极大的方便某一领域内的特征点的查找与匹配&#xff09;。单目相机初始化操作&#xff1a;通过特征点匹配&#xff0c;使用RANSACDLC计算H矩阵&#xff0c;并根据…

源同步方法与注意事项

2021年的信息安全攻防演练比2020年来的稍早了一些&#xff0c;还是一样的配方&#xff0c;还是一样的味道。检查单位的YUM源&#xff0c;发现没有CentOS 7.9的&#xff0c;排查后发现原来是中科大的rsync同步地址放生了变化&#xff0c;导致源同步失败。改一下地址就好&#xf…

Android开发教程 - 使用Data Binding(二)集成与配置

本系列目录 使用Data Binding&#xff08;一&#xff09;介绍使用Data Binding&#xff08;二&#xff09;集成与配置使用Data Binding&#xff08;三&#xff09;在Activity中的使用使用Data Binding&#xff08;四&#xff09;在Fragment中的使用使用Data Binding&#xff08…

Java封装(速读版)

封装就是使用公共方法对私有成员变量进行操作&#xff08;赋值或获取&#xff09;&#xff0c;这样做可以防止该类的代码和数据被其他类 定义的代码随意访问&#xff0c;有助于数据的安全。–我们可以通过修改成员变量的属性&#xff08;一般为private&#xff09;&#xff0c;…