【一个蒟蒻的挣扎】LCA (倍增)
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
struct edge{
int next,to;
edge(){
}
edge(int a,int b){
next=a; to=b;
}
}E[];//建一个图……
int f[][],dep[],first[],tot;
int n,m,root;
void add_to_edge(int x,int y)
{
E[++t]=edge(first[x],y);
first[x]=t;
}//连边(无向图连两次哦)
void dfs(int x,int fa)
{
f[x][]=fa;
dep[x]=dep[fa]+;
//初始化 , 它的深度是它父亲的深度+1,x 往上倍增 2^0 层 是它的父亲
int k=ceil(log(dep[x])/log());//倍增上限
for (int i=; i<=k; i++)
{
f[x][i]=f[f[x][i-]][i-];
}//f数组存预处理的值,f[x][i]存的是x向上倍增
for (int i=first[x]; i; i=E[i].next)
{
int pos=E[i].to;
if (pos!=fa)//防止死循环,由于是存了两次所以E[i].to会连向它的父亲
dfs(pos,x);
}
}//预处理
int n,m,root;
void LCA()
{
if (dep[x]<dep[y]) swap(x,y);
int k1=dep[x]-dep[y];
int k2=ceil((log(n))/log());
for (int i=; i<=k2; i++)
{
if (k1&(<<i))
x=fa[x][i];
}//向上跳!!
if (x==y) return x;//两者在同一层并且相等那么x 就是它们的共同祖先
int k3=(log(dep[x])/log());
for (int i=k3; i>=; i--)
{
if (f[x][i]!=f[y][i])
{
x=f[x][i]; y=f[y][i];
}//倍增
}
return f[x][];
}
int main()
{
cin>>n>>m>>root;
for (int i=; i<=m; i++)
{
int x,y;
cin>>x>>y;
add_to_edge(x,y);
add_to_edge(y,s);
}
dfs(root,); }
还是济南集训的内容,让人头秃(不得不说两个老师讲了两遍我勉勉强强才搞懂一点点)
首先来看:
LCA的含义
Least Common Ancestors
LCA就是最近公共祖先,至于它的含义,我觉得例题写的看起来会更清楚,请看:
好的,明白了它的含义后,我们很容易想到朴素算法:
树上倍增算法
核心思想:
- 令F[x][n]表示x的2^n级祖先是谁.
- 所以:F[x][n] = F[F[x][n – 1]][n – 1].
- 对于两个点x, y.,求他们的LCA
- 先把x, y提到同一高度.(方便向上进行倍增)
- N从大到小枚举.(从高往低跳)
- 查询F[x][n], F[y][n]是不是相等(比较倍增后的祖先,防止误判)
- 如果是的话说明n太大了,把n改小点.(最近公共祖先的祖先一定是他们的共同祖先)
- 不是的话就说明n不大,可以把x, y上移.(这个很容易理解吧)
#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
const int maxn = ;
const int maxe = ;
int n,m,root; struct line
{
int from,to;
line(){}//空构造函数 line p;
line(int A,int B){
//构造函数 line L=line(1,2);
from=A;to=B;
}
}edge[maxe];
//上面是新建一个树 int last[maxn],_next[maxe],e;
//last[x]表示以x为起点的最后一条边(的编号)
//_next[i]表示与第i条边起点相同的上一条边(的编号) void add_edge(int x,int y)
{
edge[++e]=line(x,y);
_next[e]=last[x];
last[x]=e;
}
//存边 int Fa[maxn][],Dep[maxn]; void dfs(int x,int fa)
{
int i,k,y;
Fa[x][]=fa;//当前节点x的父亲节点fa
Dep[x]=Dep[Fa[x][]]+; //x的深度是它父亲节点的深度+1
//记录当前节点的深度
k=ceil(log(Dep[x])/log()); //ceil函数是向上取整
//x往上倍增的上限
for(i=;i<=k;i++)Fa[x][i]=Fa[Fa[x][i-]][i-];
//倍增计算祖先 ,记录
for(int i=last[x];i;i=_next[i])//枚举与x相邻的边
{
int v=edge[i].to;
if(v!=fa)dfs(v,x);
}
} int LCA(int x,int y)
{
int i,k,s;
s=ceil(log(n)/log()); //该树倍增最大可能的上限
if(Dep[x]<Dep[y])swap(x,y); //交换x和y的值
/////////////x往上走k层,让x与y处于同一层 //////////
k=Dep[x]-Dep[y];
for(i=;i<=s;i++)
if(k&(<<i))x=Fa[x][i];
if(x==y)return x; //x==y时,x就是最近公共祖先
///////////////////////////////////////////////////
s=ceil(log(Dep[x])/log()); //计算向上倍增的上限
for(i=s;i>=;i--)
if(Fa[x][i]!=Fa[y][i]){ x=Fa[x][i]; y=Fa[y][i]; }
return Fa[x][];
} int main()
{
int i,j,k;
cin>>n>>m>>root;
for(i=;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add_edge(x,y);
add_edge(y,x);//它是树,也就是无向图,所以存两次边
}
dfs(root,);//预处理
for(i=;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",LCA(x,y));
} }
代码(带注释)
OK吗?
这里建议去练练板子,指路-> https://www.luogu.org/problem/P3379
(哇我居然可以写蓝题了哎!!可喜可贺)
感谢观看 ありがとうございます
【一个蒟蒻的挣扎】LCA (倍增)的更多相关文章
- 【一个蒟蒻的挣扎】最小生成树—Kruskal算法
济南集训第五天的东西,这篇可能有点讲不明白提前抱歉(我把笔记忘到别的地方了 最小生成树 概念:一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的 ...
- 【一个蒟蒻的挣扎】单源最短路(Dijkstra)
赛前没啥时间好好解释了,还有三天2019CSP,大家加油啊!!! ヾ(◍°∇°◍)ノ゙ 背掉它就好啦!!! 我觉得我这一版打得还行就放上来了 #include<cstdio> #inclu ...
- noip2013Day2T3-华容道【一个蒟蒻的详细题解】
描述 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间. 小 B 玩的华容道与经典的 ...
- 一个蒟蒻对FFT的理解(蒟蒻也能看懂的FFT)
建议同学们先自学一下"复数(虚数)"的性质.运算等知识,不然看这篇文章有很大概率看不懂. 前言 作为一个典型的蒟蒻,别人的博客都看不懂,只好自己写一篇了. 膜拜机房大佬 HY 一. ...
- 这是一个蒟蒻的计划……QAQ
感觉像我这种拖拉的人很有可能是完成不了的,挂上来相当于监督我自己啦QWQ [学习计划] [√]1.去看Trie树!!! yyb学长的blog 2.KMP还有AC自动机 先贴两个链接在这里吧:KMP ...
- 一个蒟蒻的解题过程记录——洛谷P1003 铺地毯
这到题算是我“火线回归”后码的第一道题,病好了心情不错,发篇博客分享一下 目录: ·题目描述 ·题目分析 ·解题思路 ·代码实现 ·总结 ·题目描述: 为了准备一场特殊的颁奖典礼,组织者在会场的一片矩 ...
- 论一个蒟蒻的脑子里可以有多少坑(貌似咕了……目前更新保持在noip阶段)
就是错题整理了,其实也会把一些不该犯的失误整进来. 其实之前一直拖着不想写,直到某次模拟赛,看错了2道题,顺便爆了一道题的int(没错第一个点就会爆)之后爆零了,吓得我赶紧把这篇博客搞出来了..... ...
- 蒟蒻kc的垃圾数列
题目背景 在某教练的强迫之下,我一个蒟蒻居然出题了!!!出题了!!!(数据太水别找我qwq) 好的,JL说好的一题100快拿来 题目描述 首先,给你一个空的长度为n的序列(废话) 然后,你有一系列神奇 ...
- 算法描述》LCA两三事(蒟蒻向)
LCA是图论中常用的解决树形结构子问题的工具,这一问题一般需要用一个简短的子函数直接解决,但是这对于广大蒟蒻们仍然是一个不小的问题. LCA是指在树形结构中两点的最近公共祖先,对于这个问题,直接向上找 ...
随机推荐
- DOM导航与DOM事件
HTML DOM 导航 通过 HTML DOM,能够使用节点关系在节点树中导航. ㈠HTML DOM 节点列表 getElementsByTagName() 方法返回节点列表.节点列表是一个节点数组. ...
- codevs 5969 [AK]刻录光盘x
题目描述 Description • 在FJOI2010夏令营快要结束的时候,很多营员提出来要把整个夏令营期间的资料刻录成一张光盘给大家,以便大家回去后继续学 ...
- Qtcreator 之中文目录
由于编码格式问题, qtcreator 所有关于目录的引用和存放均不出现中文,否则编译可以通过,运行时 crashed !!!
- python学习之路(13)
列表生成式 列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式. 举个例子,要生成list [1, 2, 3, 4, 5, 6, 7, ...
- LeetCode 93. 复原IP地址(Restore IP Addresses)
题目描述 给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式. 示例: 输入: "25525511135" 输出: ["255.255.11.135&qu ...
- leetcode-easy-sorting and searching- 278 First Bad Version
mycode 96.42 # The isBadVersion API is already defined for you. # @param version, an integer # @ret ...
- AM中修改套料板的尺寸
- Android 面试汇总<三>
1.3 计算机网络 基础 Q:五层协议的体系结构分别是什么?每一层都有哪些协议? 技术点:网络模型.协议 思路:分条解释每层名字以及协议 参考回答: 物理层 数据链路层:逻辑链路控制LLC.媒体接入控 ...
- zabbix服务器性能监控工具的安装一
Linux下安装zabbix需要有LNMP运行环境,本篇记录安装LNMP的过程 目录 1.准备工作 2.安装mysql 3.安装nginx 4.安装php 1.准备工作 1.1准备一台centos6. ...
- WebSocket-Node
WebSocket Client & Server Implementation for Node 参考资料:[https://github.com/theturtle32/WebSocket ...