倍增 LCA
以NOIP2013提高组day1 最后一道题为例来学的倍增和lca。其实这套题早就做过了,倍增和lca也学过,只不过当时没有理解清楚,所以今天再次学了一遍,虽然没有时间编程序了,但是先把思路和做法在这里梳理一遍,下次来编。
首先,倍增。(树上倍增)
f[i][j]表示在 j 节点向上跳2^ i 步后的节点。由2^ i =2^( i-1)+2^(i-1)可以得到递推式:f[i][j]=f[i-1][f[i-1][j]]。解释:从j节点向上跳2^ i 就相当于从j节点向上先跳2^(i-1)步到得节点,再从这个节点向上跳2^(i-1)步所到的点。
所以得到:
void bz()//倍增
{
for(int i=;i<=;i++)//i根据题意(深度)调大小
for(int j=;j<=n;j++)
fa[i][j]=fa[i-][fa[i-][j]];
}
然后就是找lca(最近公共祖先)
在这之前,首先要明确这两个点在树上的深度,先将较深的点向上跳到与另一点一样高(需要两点的深度差dh),然后再一起向上跳到最近公共祖先。怎么才能使两个点在同一深度呢?有两种方法,这里讲二进制的方法。深度差可以表示为二进制形式,如当dh=5时,为101,即这个点要在为1 的地方跳,先跳2^0步到一个节点,再从这个节点向上跳2^2步。可以用 if (1<< i & dh) 判断,当不等于0时,说明dh在第 i 位为1 ,需要跳,等于0时不需要跳就不管,每次更新跳到位置。
for(int i=;i<=;i++)//使两个点深度相同
{
if(<<i&dh)//位运算
{
// t1=min(t1,minax[i][s]);
s=fa[i][s];
}
}
然后就是两个点一起向上跳到公共祖先,只需判断他们跳到的点是不是相同就可以了,因为如果超出了最近公共祖先那么他们跳到的节点就一定是同一节点,这时i 不可取,将 i 倒序循环,这样如果超过lca就会跳较少的步数到下面一点来判断是不是lca,如果这个时候又跳得太小了,那么更新现在跳到的节点,i 继续减小,从这个节点继续向上跳,重复上面的判断,由于跳的步数越来越少,越来越接近lca,那么最后一次一定是最接近lca的,这时,一定是跳两步多了,跳一步少了,所以刚好在lca下一个节点处,再加上1 即可。
int lca(int s,int v)//找最近公共祖先,并求出最小值
{
int t1=INF,t2=INF;//两边子树最小值
if(F(s)!=F(v))return -;//判断是否连通
if(depth[v]>depth[s])//保证s在v下面
swap(s,v);
int dh=depth[s]-depth[v];
for(int i=;i<=;i++)//使两个点深度相同
{
if(<<i&dh)//位运算
{
t1=min(t1,minax[i][s]);
s=fa[i][s];
} }
if (s==v) return t1; //判断是否已经满足
for(int i=;i>=;i--)
{
if(fa[i][s]!=fa[i][v])
{
t1=min(t1,minax[i][s]);
t2=min(t2,minax[i][v]);
s=fa[i][s];
v=fa[i][v];
}
}
//此时两点都在最近公共祖先的下面,只需再向上走一步
t1=min(t1,minax[][s]);
t2=min(t2,minax[][v]);
return min(t1,t2);
}
下来自己写一遍。。。谢谢anantheparty的博客。
2016 10 09
今天把货车运输这道题A了。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define maxn 10005
#define inf 100005
#define INF 12345678
using namespace std;
int n,m,q,fat[maxn],deth[maxn];
int tot,he[maxn],ne[inf],to[inf],w[inf];
int mimax[][maxn],f[][maxn];
bool notin[inf],flag[maxn];//notin[inf] not notin[maxn] RE
struct pp{
int x,y,v;
};
pp road[inf];
const int comp(const pp&a,const pp&b )
{
return a.v>b.v;
}
void add(int a,int b,int c)
{
tot++;to[tot]=b;ne[tot]=he[a];w[tot]=c;he[a]=tot;
}
int find(int a)
{
if (fat[a]!=a) return fat[a]=find(fat[a]);
return fat[a];
}
void kruskal()
{
for (int i=;i<=n;i++)
fat[i]=i;
for (int i=;i<=*m;i++)
{
int r1=find(road[i].x),r2=find(road[i].y);
if (r1!=r2) fat[r2]=r1;
else notin[i]=true;
}
}
void dfs(int u)
{
for (int i=he[u];i;i=ne[i])
if (!flag[to[i]]){
flag[to[i]]=;
deth[to[i]]=deth[u]+;
f[][to[i]]=u;
mimax[][to[i]]=w[i];//mimax[0][to[i]]
dfs(to[i]);
}
}
void bz()
{
for (int i=;i<=;i++)// i=1!!!
for (int j=;j<=n;j++)
{
f[i][j]=f[i-][f[i-][j]];
mimax[i][j]=min(mimax[i-][j],mimax[i-][f[i-][j]]);//mimax[i-1][j],f[i-1][j]
}
}
int lca(int a,int b)
{
int r1=INF,r2=INF;
if (find(a)!=find(b)) return -;
if (deth[a]<deth[b]) swap(a,b);
int d=deth[a]-deth[b];
for (int i=;i<=;i++)
{
if (<<i & d)
{
r1=min(mimax[i][a],r1);
a=f[i][a];
}
}
if (a==b) return r1;
for (int i=;i>=;i--)
{
if (f[i][a]!=f[i][b])
{
r1=min(mimax[i][a],r1);
r2=min(mimax[i][b],r2);
a=f[i][a];
b=f[i][b];
}
}
r1=min(r1,mimax[][a]);//!
r2=min(r2,mimax[][b]);//! 还有一步
return min(r1,r2);
}
int main()
{
// freopen("truck_lca.in","r",stdin);
cin>>n>>m;
for (int i=;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
road[i*-].x=a;road[i*].x=b;
road[i*-].y=b;road[i*].y=a;
road[i*-].v=c;road[i*].v=c;
}
sort(road+,road++*m,comp);
kruskal();
for (int i=;i<=*m;i++)
if (!notin[i]) {
add(road[i].x,road[i].y,road[i].v);
add(road[i].y,road[i].x,road[i].v);
}
for (int i=;i<=n;i++)
if (!deth[i]){
int r=find(i);
deth[r]=;
flag[r]=;
dfs(r);
}
bz();
cin>>q;
for (int i=;i<=q;i++)
{
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",lca(a,b));
}
return ;
}
还是有很多小细节需要注意啊。。。
倍增 LCA的更多相关文章
- [板子]倍增LCA
倍增LCA板子,没有压行,可读性应该还可以.转载请随意. #include <cstdio> #include <cstring> #include <algorithm ...
- 洛谷P3128 [USACO15DEC]最大流Max Flow [倍增LCA]
题目描述 Farmer John has installed a new system of pipes to transport milk between the stalls in his b ...
- Gym100685G Gadget Hackwrench(倍增LCA)
题目大概说一棵边有方向的树,q个询问,每次询问结点u是否能走到v. 倍增LCA搞即可: 除了par[k][u]表示u结点往上走2k步到达的结点, 再加上upp[k][u]表示u结点往上走2k步经过边的 ...
- Codeforces 418d Big Problems for Organizers [树形dp][倍增lca]
题意: 给你一棵有n个节点的树,树的边权都是1. 有m次询问,每次询问输出树上所有节点离其较近结点距离的最大值. 思路: 1.首先是按照常规树形dp的思路维护一个子树节点中距离该点的最大值son_di ...
- hdu 4674 Trip Advisor(缩点+倍增lca)
花了一天半的时间,才把这道题ac= = 确实是道好题,好久没敲这么长的code了,尤其是最后的判定,各种销魂啊~ 题目中给出的条件最值得关注的就是:每个点最多只能在一个环内->原图是由一个个边连 ...
- Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序
题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s 内存限制:512.0MB 总提交次数:196 AC次数:65 平均分: ...
- codevs 1036 商务旅行 (倍增LCA)
/* 在我还不知道LCA之前 暴力跑的SPFA 70分 三个点TLE */ #include<iostream> #include<cstdio> #include<cs ...
- hdu 2586 How far away ?倍增LCA
hdu 2586 How far away ?倍增LCA 题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2586 思路: 针对询问次数多的时候,采取倍增 ...
- 洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)
洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...
- 洛谷P2633 Count on a tree(主席树,倍增LCA)
洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ...
随机推荐
- caffe中的Blob块
首先说明:Blob定义了一个类模板. 让我们看一下Blob的头文件里有什么哈: 定义了一个全局变量: const ; 看看它的构造函数: Blob() : data_(), diff_(), coun ...
- css技术和实例
今天,我为大家收集精选了30个使用纯CSS完成的强大实践的优秀CSS技术和实例,您将在这里发现很多与众不同的技术,比如:图片集.阴影效果.可扩展按钮.菜单等-这些实例都是使用纯CSS和HTML实现的. ...
- 如何查看与刷新DNS本地缓存
如何查看与刷新DNS本地缓存 一.查看DNS本地缓存 在cmd窗口输入:ipconfig/displaydns 二.刷新DNS本地缓存 在cmd窗口输入:ipconfig/flushdns 之后输入: ...
- Android控件之RadioGroup与RadioButton(单选控件)
一.RadioGroup与RadioButton 1.什么是RadioGroup: RadioButton的一个集合,提供多选机制 2.什么是RadioButton: RadioButton包裹在Ra ...
- C语言 常用单词
main 主要的 printf(print format)格式输出 include , return ,if ,else ,switch ,case 机箱:案 ...
- html list <==> unformatted list
两者的区别很大不得不擦呢,任何两个东西的差别都很大,不得混淆.---一个有ul/ol的选择,一个没有
- 【bzoj1057】棋盘制作
题意 给定\(n*m\)的棋盘,每个格子有0或1其中的一种颜色. 求一个最大的正方形,满足正方形内0和1相互间隔. 求一个最大的矩形,满足矩形内0和1相互间隔. \(n,m\leq 2000\) 分析 ...
- 使用Beanstalkd实现队列
Beanstalkd可以想象成缓存当中的memcahe或者redise,将我们的队列任务放到内存中进行管理. 运行环境是在linux中,反正我的windows中没运行成功.../(ㄒoㄒ)/~~ 首先 ...
- FCKeditor jsp配置
FCKeditor jsp配置 FCKeditor是sourceforge.net上面的一个开源项目,主要是实现在线网页编辑器的功能,可以让web程序拥有如MS Word这样强大的编辑功能.官方网站为 ...
- angular 模板 小例子
参考网站:https://docs.angularjs.org/tutorial/step_09 先看下目录结构 新建个空文件夹, 输入命令: express --view ejs cnpm inst ...