AC日记——【模板】最近公共祖先(LCA)洛谷 P3379
题目描述
如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。
输入输出格式
输入格式:
第一行包含三个正整数N、M、S,分别表示树的结点个数、询问的个数和树根结点的序号。
接下来N-1行每行包含两个正整数x、y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树)。
接下来M行每行包含两个正整数a、b,表示询问a结点和b结点的最近公共祖先。
输出格式:
输出包含M行,每行包含一个正整数,依次为每一个询问的结果。
输入输出样例
5 5 4
3 1
2 4
5 1
1 4
2 4
3 2
3 5
1 2
4 5
4
4
1
4
4
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=10,M<=10
对于70%的数据:N<=10000,M<=10000
对于100%的数据:N<=500000,M<=500000
样例说明:
该树结构如下:

第一次询问:2、4的最近公共祖先,故为4。
第二次询问:3、2的最近公共祖先,故为4。
第三次询问:3、5的最近公共祖先,故为1。
第四次询问:1、2的最近公共祖先,故为4。
第五次询问:4、5的最近公共祖先,故为4。
故输出依次为4、4、1、4、4。
思路:
树剖。
来,上代码:
#include <cstdio>
#include <iostream>
#include <algorithm> #define maxn 500001 using namespace std; struct EdgeType {
int to,next;
};
struct EdgeType edge[maxn<<]; int if_z,n,m,s,num,f[maxn],deep[maxn];
int belong[maxn],size[maxn],cnt,head[maxn]; char Cget; inline void read_int(int &now)
{
now=,if_z=,Cget=getchar();
while(Cget>''||Cget<'')
{
if(Cget=='-') if_z=-;
Cget=getchar();
}
while(Cget>=''&&Cget<='')
{
now=now*+Cget-'';
Cget=getchar();
}
now*=if_z;
} inline void edge_add(int from,int to)
{
edge[++num].to=from,edge[num].next=head[to],head[to]=num;
edge[++num].to=to,edge[num].next=head[from],head[from]=num;
} void search(int now,int fa)
{
int pos=cnt++;
f[now]=fa,deep[now]=deep[fa]+;
for(int i=head[now];i;i=edge[i].next)
{
if(edge[i].to==fa) continue;
search(edge[i].to,now);
}
size[now]=cnt-pos;
} void search_(int now,int chain)
{
int pos=;
belong[now]=chain;
for(int i=head[now];i;i=edge[i].next)
{
if(edge[i].to==f[now]) continue;
if(size[pos]<size[edge[i].to]) pos=edge[i].to;
}
if(pos!=) search_(pos,chain);
else return ;
for(int i=head[now];i;i=edge[i].next)
{
if(edge[i].to==pos||edge[i].to==f[now]) continue;
search_(edge[i].to,edge[i].to);
}
} inline int lca(int x,int y)
{
while(belong[x]!=belong[y])
{
if(deep[belong[x]]<deep[belong[y]]) swap(x,y);
x=f[belong[x]];
}
if(deep[x]<deep[y]) return x;
else return y;
} int main()
{
read_int(n),read_int(m),read_int(s);
int from,to;
for(int i=;i<n;i++)
{
read_int(from),read_int(to);
edge_add(from,to);
}
search(s,),cnt=,search_(s,s);
for(int i=;i<=m;i++)
{
read_int(from),read_int(to);
printf("%d\n",lca(from,to));
}
return ;
}
附,70分暴力找lca:
#include <cstdio>
#include <algorithm> #define maxn 500001 using namespace std; struct EdgeType {
int to,next;
};
struct EdgeType edge[maxn<<]; int f[maxn],head[maxn],num;
int n,m,s,if_z,dfn[maxn],cnt; char Cget; inline void read_int(int &now)
{
now=,if_z=,Cget=getchar();
while(Cget>''||Cget<'')
{
if(Cget=='-') if_z=-;
Cget=getchar();
}
while(Cget>=''&&Cget<='')
{
now=now*+Cget-'';
Cget=getchar();
}
now*=if_z;
} inline void edge_add(int from,int to)
{
edge[++num].to=from,edge[num].next=head[to],head[to]=num;
edge[++num].to=to,edge[num].next=head[from],head[from]=num;
} void search(int now,int fa)
{
dfn[now]=++cnt,f[now]=fa;
for(int i=head[now];i;i=edge[i].next)
{
if(edge[i].to==fa) continue;
search(edge[i].to,now);
}
} inline int lca(int x,int y)
{
if(dfn[x]<dfn[y]) swap(x,y);
while(dfn[x]>dfn[y]) x=f[x];
while(dfn[y]>dfn[x]) y=f[y];
return y;
} int main()
{
read_int(n),read_int(m),read_int(s);
int from,to;
for(int i=;i<n;i++)
{
read_int(from),read_int(to);
edge_add(from,to);
}
search(s,);
for(int i=;i<=m;i++)
{
read_int(from),read_int(to);
printf("%d\n",lca(from,to));
}
return ;
}
AC日记——【模板】最近公共祖先(LCA)洛谷 P3379的更多相关文章
- [模板] 最近公共祖先/lca
简介 最近公共祖先 \(lca(a,b)\) 指的是a到根的路径和b到n的路径的深度最大的公共点. 定理. 以 \(r\) 为根的树上的路径 \((a,b) = (r,a) + (r,b) - 2 * ...
- AC日记——[ZJOI2015]幻想乡战略游戏 洛谷 P3345
[ZJOI2015]幻想乡战略游戏 思路: 树剖暴力转移: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 1 ...
- AC日记——[JLOI2014]松鼠的新家 洛谷 P3258
题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在”树“上. 松鼠想邀请小熊维尼前 ...
- AC日记——[USACO15DEC]最大流Max Flow 洛谷 P3128
题目描述 Farmer John has installed a new system of pipes to transport milk between the stalls in his b ...
- AC日记——[USACO10MAR]仓配置Barn Allocation 洛谷 P1937
[USACO10MAR]仓配置Barn Allocation 思路: 贪心+线段树维护: 代码: #include <bits/stdc++.h> using namespace std; ...
- AC日记——[HNOI2010]BOUNCE 弹飞绵羊 洛谷 P3203
[HNOI2010]BOUNCE 弹飞绵羊 思路: SBlct: 代码: #include <bits/stdc++.h> using namespace std; #define max ...
- AC日记——斐波那契数列 洛谷 P1962
斐波那契数列 思路: 矩阵快速幂: 来,上代码: #include <cstdio> #include <cstring> #include <iostream> ...
- AC日记——[USACO09JAN]全流Total Flow 洛谷 P2936
题目描述 Farmer John always wants his cows to have enough water and thus has made a map of the N (1 < ...
- AC日记——[USACO11DEC]牧草种植Grass Planting 洛谷 P3038
题目描述 Farmer John has N barren pastures (2 <= N <= 100,000) connected by N-1 bidirectional road ...
- AC日记——让我们异或吧 洛谷 P2420
题目描述 异或是一种神奇的运算,大部分人把它总结成不进位加法. 在生活中…xor运算也很常见.比如,对于一个问题的回答,是为1,否为0.那么: (A是否是男生 )xor( B是否是男生)=A和B是否能 ...
随机推荐
- Windows7设置局域网文件共享
首先要实现共享必须设置共享的机器与访问共享的机器在同一个工作组中. 右键桌面上的计算机图标=>属性 如果不一样的话,就需要点击[更改设置] 右键要共享的文件或者文件夹,点击[共享]打开共享标签: ...
- Python使用gevent实现协程
Python中多任务的实现可以使用进程和线程,也可以使用协程. 一.协程介绍 协程,又称微线程.英文名Coroutine.协程是Python语言中所特有的,在其他语言中没有. 协程是python中另外 ...
- GoF23种设计模式之结构型模式之装饰模式
一.概述 动态地给一个对象添加一些额外的职责.装饰模式比生成子类更为灵活. 二.适用性 1.在不影响其他对象的情况下,以动态.透明的方式给但个对象添加职责. 2.处理那些可以撤销的职责. 3.当不能采 ...
- [solution]腾讯TEG_计算广告组_算法题
度娘笔试归来,题目实打实的,感觉真心不易,上百号人就抢那么几个坑......只恨自己平时积累太少啊~ 故曝一道鹅厂面试用的算法题(当时我就死在了这题上),来为度娘家攒一下RP~ 题目: 对于长度为N的 ...
- Cinder配置多Ceph后端步骤
1. 检查cinder当前backend配置 使用cinder service-list,查看cinder-volume服务的Host字段格式. 旧版格式: 新版格式: 旧版中Host字段是cinde ...
- 配置LAMP环境
对我这种Linux小菜鸡来说,集成环境是最好的选择. 一,下载wget --no-check-certificate https://github.com/teddysun/lamp-yum/arch ...
- Django基于Pycharm开发之二 [使用django adminSite]
在使用django自带的adminsite的时候,有以下内容需要做. 1.数据迁移,管理表的创建. 2.启用本地化 (setting.py的配置) 一.数据迁移,默认情况下,安装django之后,dj ...
- Django Form one
前戏: FromData:三种方式获取FromData 1. 创建一个FromData 的对象,然后再用append 的方法追个添加键值对 var formdata = new FormData(); ...
- 大数据学习——scala函数与方法
package com /** * Created by Administrator on 2019/4/8. */ object TestMap { def ttt(f: Int => Int ...
- python学习--python 连接SQLServer数据库(两种方法)
1. python 学习.安装教程参照: http://www.runoob.com/python/python-tutorial.html 2. 集成开发环境 JetBrains PyCharm C ...