LUOGU P4281 [AHOI2008]紧急集合 / 聚会 (lca)
解题思路
可以通过手玩或打表发现,其实要选的点一定是他们三个两两配对后其中一对的$lca$上,那么就直接算出来所有的$lca$,比较大小就行了。
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<cstdlib>
- #include<algorithm>
- using namespace std;
- const int MAXN = ;
- inline int rd(){
- int x=,f=;char ch=getchar();
- while(!isdigit(ch)) {f=ch=='-'?:;ch=getchar();}
- while(isdigit(ch)) {x=(x<<)+(x<<)+ch-'';ch=getchar();}
- return f?x:-x;
- }
- int ans,p,n,m,head[MAXN],cnt,num;
- int to[MAXN<<],nxt[MAXN<<];
- int id[MAXN],dep[MAXN],top[MAXN],fa[MAXN],siz[MAXN],son[MAXN];
- inline void add(int bg,int ed){
- to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;
- }
- void dfs1(int x,int f,int d){
- dep[x]=d,fa[x]=f,siz[x]=;register int maxson=,u;
- for(register int i=head[x];i;i=nxt[i]){
- u=to[i];if(u==f) continue;
- dfs1(u,x,d+);siz[x]+=siz[u];
- if(siz[u]>maxson) {maxson=u;son[x]=u;}
- }
- }
- void dfs2(int x,int topf){
- top[x]=topf;id[x]=++num;if(!son[x]) return;dfs2(son[x],topf);int u;
- for(register int i=head[x];i;i=nxt[i]){
- u=to[i];if(u==fa[x] || u==son[x]) continue;dfs2(u,u);
- }
- }
- inline int lca(int x,int y){
- while(top[x]!=top[y]){
- if(dep[top[x]]>dep[top[y]]) x=fa[top[x]];
- else y=fa[top[y]];
- }
- return dep[x]>dep[y]?y:x;
- }
- inline void LCA(int x,int y,int z){
- register int tmp,dis,all;tmp=lca(x,y);all=lca(tmp,z);
- dis=dep[x]+dep[y]-dep[tmp]+dep[z]-*dep[all];ans=dis;p=tmp;dis+=dep[tmp];
- tmp=lca(x,z);dis-=dep[tmp];if(ans>dis) {ans=dis;p=tmp;}
- dis+=dep[tmp];tmp=lca(y,z);dis-=dep[tmp];if(ans>dis) {ans=dis;p=tmp;}
- }
- void out(int x){
- if(!x) return;
- out(x/);putchar(''+x%);
- }
- int main(){
- n=rd(),m=rd();int x,y,z;
- for(register int i=;i<n;i++){
- x=rd(),y=rd();add(x,y),add(y,x);
- }
- dfs1(,,),dfs2(,);
- while(m--) {
- x=rd(),y=rd(),z=rd();ans=1e9;
- LCA(x,y,z);out(p);putchar(' ');if(!ans) putchar('');else out(ans);
- putchar('\n');
- }
- return ;
- }
LUOGU P4281 [AHOI2008]紧急集合 / 聚会 (lca)的更多相关文章
- P4281 [AHOI2008]紧急集合 / 聚会[LCA]
解析 蒟蒻用的办法比较蠢,不如上面的各位大佬,直接化成一个式子了,我还是分类讨论做的. 下面正文. 猜想:最优集合点一定是三点任意两对点对应的路径的交点. 不妨这样想,如果任意两个人经过同一条路径,那 ...
- P4281 [AHOI2008]紧急集合 / 聚会
P4281 [AHOI2008]紧急集合 / 聚会 lca 题意:求3个点的lca,以及3个点与lca的距离之和. 性质:设点q1,q2,q3 两点之间的lca t1=lca(q1,q2) t2=lc ...
- Luogu 4281 [AHOI2008]紧急集合 / 聚会
BZOJ 1832 写起来很放松的题. 首先发现三个点在树上一共只有$3$种形态,大概长这样: 这种情况下显然走到三个点的$lca$最优. 这种情况下走到中间那个点最优. 这种情况下走到$2$最优. ...
- [AHOI2008]紧急集合 / 聚会(LCA)
[AHOI2008]紧急集合 / 聚会 题目描述 欢乐岛上有个非常好玩的游戏,叫做"紧急集合".在岛上分散有N个等待点,有N-1条道路连接着它们,每一条道路都连接某两个等待点,且通 ...
- LCA【p4281】[AHOI2008]紧急集合 / 聚会
Description 欢乐岛上有个非常好玩的游戏,叫做"紧急集合".在岛上分散有N个等待点,有N-1条道路连接着它们,每一条道路都连接某两个等待点,且通过这些道路可以走遍所有的等 ...
- 【题解】洛谷P4281 [AHOI2008] 紧急集合(求三个点LCA)
洛谷P4281:https://www.luogu.org/problemnew/show/P4281 思路 答案所在的点必定是三个人所在点之间路径上的一点 本蒟蒻一开始的想法是:先求出2个点之间的L ...
- [AHOI2008]紧急集合 / 聚会
题目描述 欢乐岛上有个非常好玩的游戏,叫做“紧急集合”.在岛上分散有N个等待点,有N-1条道路连接着它们,每一条道路都连接某两个等待点,且通过这些道路可以走遍所有的等待点,通过道路从一个点到另一个点要 ...
- 洛谷 P4281 [AHOI2008] 紧急集合 题解
挺好的一道题,本身不难,就把求两个点的LCA变为求三个点两两求LCA,不重合的点才是最优解.值得一提的是,最后对答案的处理运用差分的思想:假设两点 一点深度为d1,另一点 深度为d2,它们LCA深度为 ...
- 「AHOI2008」「LuoguP4281」紧急集合 / 聚会(LCA
题目描述 欢乐岛上有个非常好玩的游戏,叫做“紧急集合”.在岛上分散有N个等待点,有N-1条道路连接着它们,每一条道路都连接某两个等待点,且通过这些道路可以走遍所有的等待点,通过道路从一个点到另一个点要 ...
随机推荐
- plugin python was not installed: Cannot download ''
problem: plugin python was not installed: Cannot download ''........ 1. the first method of resoluti ...
- AtCoder ABC 130F Minimum Bounding Box
题目链接:https://atcoder.jp/contests/abc130/tasks/abc130_f 题目大意 给定地图上 N 个点的坐标和移动方向,它们会以每秒 1 个单位的速度移动,设 A ...
- linux 网络监控软件nethogs iftop
1.nethogs yum -y install nethogs 装上了这个工具之后,使用起来就非常简单了.敲入nethogs 就会给出所有的信息.看下面的例子. root@ubuntu2:~# ne ...
- sklearn提供的自带数据集
sklearn 的数据集有好多个种 自带的小数据集(packaged dataset):sklearn.datasets.load_<name> 可在线下载的数据集(Downloaded ...
- pycharm快捷键表
快捷键 作用 ctrl(command)+c 复制 ctrl+v 粘贴 ctrl+z 撤销 ctrl+x 剪切,默认整行 ctrl+a 全选 ctrl+f 查找:选中批量修改 shift+ctrl+z ...
- vue项目使用history模式打包应该注意的地方
1.在config/index.js中将assetsPublicPath原来的’/‘修改为‘./’. build: { env: require('./prod.env'), index: path. ...
- Visual Studio Git代码管理环境部署
Visual Studio 2010 部署Git代码管理环境. 第一:首先做Git的安装和环境部署 1.下载并安装Git软件,在windows环境下的Git叫做“msysGit”,官网地址为https ...
- split的用法
split用法返回的是数组 使用split('')根据空格返回数组 使用split()返回一个完整的数组 使用split("",3)返回前三项,是单个的字母 不过要注意: 使用sp ...
- thinkphp empty标签
empty标签用于判断某个变量是否为空,用法: 大理石平台检验标准 <empty name="name"> name为空值 </empty> 如果判断没有赋 ...
- LUOGU P4042 [AHOI2014/JSOI2014]骑士游戏 (spfa+dp)
传送门 解题思路 首先设\(f[x]\)表示消灭\(x\)的最小花费,那么转移方程就是 \(f[x]=min(f[x],\sum f[son[x]] +s[x])\),如果这个转移是一个有向无环图,那 ...