标签(空格分隔): LCA


我的个人网站挂了,最近就先用这个来写博客吧。以后争取在这个网站写一些与OI无关的个人爱好的东西。


题目来源:code[VS]

倍增--在线算法

用 $f[i][j]$ 记录从 $i$ 向上跳 $2^j$ 次会跳到的位置。需 $O(nlog(n))$ 的预处理与 $O(mlog(n))$ 的查询。具体如下:

//code[VS]	P1036	LCA
#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; struct Edge
{
int from,to,next;
bool access;
Edge(int form=0,int to=0,int next=0,bool access=true):from(from),to(to),next(next),access(access) {}
}e[60100]; int depth[30100],f[30100][25],v[25],pre[30100];
int n; int c[30100];
void bfs(int s)
{
c[1] = s; depth[s] = 1;
int head = 1,tail = 1;
while (head<=tail)
{
int x = c[head++];
int v = pre[x];
while (v)
{
if (e[v].access)
{
depth[e[v].to] = depth[x] + 1;
c[++tail] = e[v].to;
f[e[v].to][0] = x;
e[v^1].access = false;
}
v = e[v].next;
}
}
} void prepare()
{
v[0] = 1;
for (int j = 1; j<=20; j++)
for (int i = 1; i<=n; i++)
{
f[i][j] = f[f[i][j-1]][j-1];
v[j] = 2*v[j-1];
}
} int LCA(int x,int y)
{ int ans=0;
if (depth[x] < depth[y]) swap(x,y); for (int i = 20;depth[x]>depth[y];i--)
if (depth[f[x][i]] >= depth[y])
{
ans += v[i];
x = f[x][i];
} if (x==y) return ans; for (int i = 20; i>=0; i--)
if (f[x][i] != f[y][i])
{
x = f[x][i];
y = f[y][i];
ans += v[i]*2;
}
ans += 2;
return ans;
} int main()
{
memset(pre,0,sizeof(pre)); scanf("%d",&n);
for (int i = 1; i<n; i++)
{
int x,y;
scanf("%d%d",&x,&y);
e[2*i] = Edge(x,y,pre[x],true);
pre[x] = 2*i;
e[2*i+1] = Edge(y,x,pre[y],true);
pre[y] = 2*i+1;
} bfs(1); prepare(); int m;
scanf("%d",&m);
int x,y=1,ans=0;
for (int i = 1; i<=m; i++)
{
x = y;
scanf("%d",&y);
ans += LCA(x,y);
} printf("%d",ans);
}

Tarjan--离线算法

对于这么一个玄学的算法,我不想说太多。。。用并查集进行维护,可以证明,每当搜到 $x$ 时,与之对应的 $y$ 所在集合的祖先一定为这两点的LCA。

//code[VS]	P1036	LCA
#include <cstdio>
#include <cstring> struct Edge
{
int from,to,next;
bool access;
Edge(int from=0,int to=0,int next=0,bool access=true):from(from),to(to),next(next),access(access) {}
}e[60100]; struct Query
{
int point,next;
Query(int point=0,int next=0):point(point),next(next) {}
}q[60100]; //fa[i]记录i的父亲,f[i]记录i指向的第一条边,fq[i]记录i指向的第一个查询
int fa[30100],f[30100],fq[30100],depth[30100];
int ans=0; //记录答案
bool b[30100]; int c[30100];
void bfs(int s) //通过广搜计算出深度与边的方向
{
c[1] = s; depth[s] = 1;
int head = 1,tail = 1;
while (head<=tail)
{
int x = c[head++];
int v = f[x];
while (v)
{
if (e[v].access)
{
e[v^1].access = false; //将该边的反向边设为false
depth[e[v].to] = depth[x] + 1;
c[++tail] = e[v].to;
}
v = e[v].next;
}
}
} int find(int x)
{
return x==fa[x]?x:fa[x]=find(fa[x]);
} void Union(int x,int y)
{
int fy = find(y);
fa[fy] = x;
} void Tarjan_LCA(int x)
{
fa[x] = x; //以x创建一个集合
int v = f[x];
while (v) //循环x的临边
{
if (e[v].access) //如果该边为正方向(即指向儿子)
{
Tarjan_LCA(e[v].to);
Union(x,e[v].to); //将x的子树与x合并
}
v = e[v].next;
}
b[x] = true; //设置该点已走过(必须在处理完儿子后设置,否则会有重复计算) v = fq[x];
while (v) //处理关于x点的查询
{
if (b[q[v].point]) //如果另一点已走过 花费=a点深度+b点深度-2*LCA(a,b)的深度
ans = ans + ( depth[x] + depth[q[v].point] - 2*depth[find(q[v].point)] );
v = q[v].next;
}
} int main()
{
memset(b,false,sizeof(b));
memset(f,0,sizeof(f));
memset(fq,0,sizeof(fq)); int n;
scanf("%d",&n);
for (int i = 1; i<n; i++)
{
int x,y;
scanf("%d%d",&x,&y);
e[2*i] = Edge(x,y,f[x],true);
f[x] = 2*i;
e[2*i+1] = Edge(y,x,f[y],true);
f[y] = 2*i+1;
} int m;
scanf("%d",&m);
int x,y=1;
for (int i = 1; i<=m; i++) //因为不知先查询到哪个点所以要存储双向变
{
x = y;
scanf("%d",&y);
q[i*2-1] = Query(y,fq[x]);
fq[x] = 2*i-1;
q[2*i] = Query(x,fq[y]);
fq[y] = 2*i;
} bfs(1); Tarjan_LCA(1); printf("%d",ans);
}

LCA专题的更多相关文章

  1. 在线倍增法求LCA专题

    1.cojs 186. [USACO Oct08] 牧场旅行 ★★   输入文件:pwalk.in   输出文件:pwalk.out   简单对比时间限制:1 s   内存限制:128 MB n个被自 ...

  2. HDU 2586——How far away ?

    Time limit 1000 ms Memory limit 32768 kB Description There are n houses in the village and some bidi ...

  3. 专题训练之LCA

    推荐几个博客:https://www.cnblogs.com/JVxie/p/4854719.html Tarjan离线算法的基本思路及其算法实现 https://blog.csdn.net/shah ...

  4. LCA(最近公共祖先)专题(不定期更新)

    Tarjan(离线)算法 思路: 1.任选一个点为根节点,从根节点开始. 2.遍历该点u所有子节点v,并标记这些子节点v已被访问过. 3.若是v还有子节点,返回2,否则下一步. 4.合并v到u上. 5 ...

  5. bryce1010专题训练——LCA

    1.Targan算法(离线) http://poj.org/problem?id=1470 /*伪代码 Tarjan(u)//marge和find为并查集合并函数和查找函数 { for each(u, ...

  6. poj3728 倍增法lca 好题!

    lca的好题!网上用st表和离线解的比较多,用树上倍增也是可以做的 不知道错在哪里,等刷完了这个专题再回来看 题解链接https://blog.csdn.net/Sd_Invol/article/de ...

  7. SPOJ 10628. Count on a tree (树上第k大,LCA+主席树)

    10628. Count on a tree Problem code: COT You are given a tree with N nodes.The tree nodes are number ...

  8. POJ 1330 Nearest Common Ancestors (LCA,倍增算法,在线算法)

    /* *********************************************** Author :kuangbin Created Time :2013-9-5 9:45:17 F ...

  9. POJ 1470 Closest Common Ancestors (LCA,离线Tarjan算法)

    Closest Common Ancestors Time Limit: 2000MS   Memory Limit: 10000K Total Submissions: 13372   Accept ...

随机推荐

  1. JavaScript作用域(链)学习笔记

    作用域是javascript老生常谈的问题,在面试题中也经常出现.此文记录本人对js作用域的理解.从以下三个方面深入探讨js作用域和js作用域链. 1.什么是作用域? 2.什么是作用域链? 3.常见面 ...

  2. Table of Contents - Jersey

    Jersey 1.19.1 Getting Started Get started with Jersey using the embedded Grizzly server Get started ...

  3. LINUX下查看php运行的用户

    <?php echo shell_exec("id -a"); ?> 打开网页,显示 uid=2(daemon) gid=2(daemon) groups=2(daem ...

  4. 2015英特尔® 实感™ (Intel® RealSense™) 动手开发实验课

    2015年英特尔® 全球实感技术动手实验课路演来到中国, 这次在中国将有北京和广州两站,包括一天的动手实验室活动 - 面向对感知计算.3D 开发和虚拟现实兴趣浓厚的开发人员.英特尔专家将会指导您如何借 ...

  5. WinDbg配置与下载 (转载)

    WinDbg配置和使用基础     WinDbg是微软发布的一款相当优秀的源码级(source-level)调试工具,可以用于Kernel模式调试和用户模式调试,还可以调试Dump文件. 1. Win ...

  6. phpmailer使用163邮件发送邮件例子

    注意:如果你的服务器安装了卖咖啡并且开户病毒最大防护功能我们需要关闭一个邮件防护哦,否则你的邮件发不出去给被这款杀毒给拦截哦. 1. 使用gmail发送的脚本 代码如下 复制代码 include(&q ...

  7. CentOS7 固定ip

    1. 进入/etc/ network-scripts/ 下ifcfg-eno16777736(文件名可能不一样,单前缀一般是ifcfg-eno) 2. vi打开 编辑  修改bootproro=&qu ...

  8. Cocos2d-JS中的cc.LabelTTF

    cc.LabelTTF是使用系统中的字体,它是最简单的标签类.cc.LabelTTF类图如下图所示,可以cc.LabelTTF继承了cc.Node类,具有cc.Node的基本特性. LabelTTF类 ...

  9. UIAlertView[警告框] [代理协议型]UIActionSheet [表单视图][代理协议型]

    ////  ViewController.h//  UIAlertViewAndUIActionSheet////  Created by hehe on 15/9/21.//  Copyright ...

  10. 九款酷炫基于jquery实现的应用及源码

    1.HTML5 Loading动画加载 五彩的圆环Loading 今天我们要分享一款基于HTML5的Loading加载动画特效,这款HTML5加载动画是一个五彩的圆环,圆环不停地转动从而体现加载正在进 ...