以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的更多相关文章

  1. [板子]倍增LCA

    倍增LCA板子,没有压行,可读性应该还可以.转载请随意. #include <cstdio> #include <cstring> #include <algorithm ...

  2. 洛谷P3128 [USACO15DEC]最大流Max Flow [倍增LCA]

    题目描述 Farmer John has installed a new system of  pipes to transport milk between the  stalls in his b ...

  3. Gym100685G Gadget Hackwrench(倍增LCA)

    题目大概说一棵边有方向的树,q个询问,每次询问结点u是否能走到v. 倍增LCA搞即可: 除了par[k][u]表示u结点往上走2k步到达的结点, 再加上upp[k][u]表示u结点往上走2k步经过边的 ...

  4. Codeforces 418d Big Problems for Organizers [树形dp][倍增lca]

    题意: 给你一棵有n个节点的树,树的边权都是1. 有m次询问,每次询问输出树上所有节点离其较近结点距离的最大值. 思路: 1.首先是按照常规树形dp的思路维护一个子树节点中距离该点的最大值son_di ...

  5. hdu 4674 Trip Advisor(缩点+倍增lca)

    花了一天半的时间,才把这道题ac= = 确实是道好题,好久没敲这么长的code了,尤其是最后的判定,各种销魂啊~ 题目中给出的条件最值得关注的就是:每个点最多只能在一个环内->原图是由一个个边连 ...

  6. Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序

    题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s   内存限制:512.0MB    总提交次数:196   AC次数:65   平均分: ...

  7. codevs 1036 商务旅行 (倍增LCA)

    /* 在我还不知道LCA之前 暴力跑的SPFA 70分 三个点TLE */ #include<iostream> #include<cstdio> #include<cs ...

  8. hdu 2586 How far away ?倍增LCA

    hdu 2586 How far away ?倍增LCA 题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2586 思路: 针对询问次数多的时候,采取倍增 ...

  9. 洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)

    洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...

  10. 洛谷P2633 Count on a tree(主席树,倍增LCA)

    洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ...

随机推荐

  1. Python中的join()函数split()函数

    函数:string.join() Python中有join()和os.path.join()两个函数,具体作用如下:     join():    连接字符串数组.将字符串.元组.列表中的元素以指定的 ...

  2. HashMap遍历

    package com.jackey.topic; import java.util.ArrayList;import java.util.HashMap;import java.util.Itera ...

  3. javascript AOP实现

    参考:http://www.cnblogs.com/rubylouvre/archive/2009/08/08/1541578.html function Person(){ this.say = f ...

  4. C语言中随机数相关问题

    用C语言产生随机数重要用到rand函数.srand函数.及宏RAND_MAX(32767),它们均在stdlib.h中进行了声明. int rand(void);//生成一个随机数 voidsrand ...

  5. jq实现某个标签内,达到一定字数后,剩下的用 ... 显示

    $(".infom_con").each(function(){ var text=$(this).find("a").text(); var len=text ...

  6. \bin\sh.exe:*** Couldn't reserve space for cygwin's heap,Win32 error 0

    Git一直使用都好好的,今天git pull的时候,报了如下的错误,\bin\sh.exe:*** Couldn't reserve space for cygwin's heap,Win32 err ...

  7. NSNotification系统通知优化

    最近在github上看到了LRNotificationObserver这个项目,看了一下实现方式,作者通过ARC机制实例化注册对象子类与关联对象的方法来管理注册对象的生命周期.从而省去了系统通知移除的 ...

  8. JavaWeb基础: 学习大纲

    JavaWeb基础: Web应用和Web服务器 JavaWeb基础: Tomcat JavaWeb基础:HTTP协议和基于Restful的架构 JavaWeb基础: Web工程配置文件 JavaWeb ...

  9. Text Justification [LeetCode]

    Problem Description:http://oj.leetcode.com/problems/text-justification/ Note: Just be careful about ...

  10. 【新手练习】类似Path的按钮,

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...