貌似求LCA使用倍增已经可以应付掉大多数需要LCA的题了..

但是有些时候$O(MlogN)$的复杂度就不可接受了

Tarjan_LCA对于每个询问采用离线处理

总复杂度为$O(M+N)$

这个复杂度几乎不可能被卡掉

简单说的话用Tarjan求LCA就是根据后序dfs的框架然后用并查集加持。

具体实现过程参加代码。

用HDU2586作为模板

//HUD 2586 Tarjan_LCA
//by Cydiater
//2016.8.15
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <queue>
#include <map>
#include <iomanip>
#include <algorithm>
using namespace std;
#define ll long long
#define up(i,j,n)       for(int i=j;i<=n;i++)
#define down(i,j,n)     for(int i=j;i>=n;i--)
const int MAXN=1e6+5;
const int oo=0x3f3f3f3f;
inline int read(){
      char ch=getchar();int x=0,f=1;
      while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
      while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
      return x*f;
}
int N,M,LINK[MAXN],len=0,dis[MAXN],fa[MAXN],tol=0,Link[MAXN],g[MAXN],T,ans[MAXN];
bool vis[MAXN];
struct edge{int y,next,v;}e[MAXN];
struct query{int y,next,lca;}q[MAXN];
namespace solution{
      inline void insert(int x,int y,int v){e[++len].next=LINK[x];LINK[x]=len;e[len].y=y;e[len].v=v;}
      inline void Insert(int x,int y){q[++tol].next=Link[x];Link[x]=tol;q[tol].y=y;}
      int get(int k){
            if(g[k]==k) return k;
            g[k]=get(g[k]);
            return g[k];
      }
      void dfs(int node,int dist,int father){
            fa[node]=father;dis[node]=dist;
            for(int i=LINK[node];i;i=e[i].next)
                  if(e[i].y!=father)
                        dfs(e[i].y,dist+e[i].v,node);
      }
      void init(){
            N=read();M=read();
            up(i,1,N-1){
                  int x=read(),y=read(),v=read();
                  insert(x,y,v);
                  insert(y,x,v);
            }
            memset(fa,0,sizeof(fa));
            memset(dis,0,sizeof(dis));
            memset(vis,0,sizeof(vis));
            dfs(1,0,0);
            up(i,1,M){
                  int x=read(),y=read();
                  Insert(x,y);
            }
      }
      void lca(int node){
            vis[node]=1;g[node]=node;
            for(int i=LINK[node];i;i=e[i].next)
                  if(!vis[e[i].y]){
                        lca(e[i].y);
                        g[e[i].y]=node;
                  }
            for(int i=Link[node];i;i=q[i].next)
                  if(vis[q[i].y]){
                        q[i].lca=get(q[i].y);
                        ans[i]=dis[node]+dis[q[i].y]-2*dis[q[i].lca];
                  }
      }
      void output(){
            up(i,1,M)printf("%d\n",ans[i]);
      }
}
int main(){
      //freopen("input.in","r",stdin);
      using namespace solution;
      T=read();
      while(T--){
            tol=0;len=0;
            memset(Link,0,sizeof(Link));
            memset(LINK,0,sizeof(LINK));
            init();
            lca(1);
            output();
      }
      return 0;
}

Tarjan_LCA的更多相关文章

  1. hud 2586 How far away ?

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=2586 How far away ? Description There are n houses in ...

  2. LCA专题

    标签(空格分隔): LCA 我的个人网站挂了,最近就先用这个来写博客吧.以后争取在这个网站写一些与OI无关的个人爱好的东西. 题目来源:code[VS] 倍增--在线算法 用 $f[i][j]$ 记录 ...

  3. LCA 各种神奇的LCA优化方法

    LCA(Least Common Ancestors) 树上问题的一种. 朴素lca很简单啦,我就不多说了,时间复杂度n^2 1.倍增LCA 时间复杂度 nlongn+klogn 其实是一种基于朴素l ...

  4. 最近公共祖先(LCA)的三种求解方法

    转载来自:https://blog.andrewei.info/2015/10/08/e6-9c-80-e8-bf-91-e5-85-ac-e5-85-b1-e7-a5-96-e5-85-88lca- ...

  5. LCA的倍增算法

    LCA,即树上两点之间的公共祖先,求这样一个公共祖先有很多种方法: 暴力向上:O(n) 每次将深度大的点往上移动,直至二者相遇 树剖:O(logn) 在O(2n)预处理重链之后,每次就将深度大的沿重链 ...

  6. NOIP2016天天爱跑步 题解报告【lca+树上统计(桶)】

    题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含 nn个 ...

  7. AC日记——货车运输 codevs

    3287 货车运输 2013年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 Descri ...

  8. LCA最近公共祖先知识点整理

    题解报告:hdu 2586 How far away ? Problem Description There are n houses in the village and some bidirect ...

  9. BZOJ3331 [BeiJing2013]压力[圆方树+树上差分]

    圆方树新技能get.具体笔记见图连通性问题学习笔记. 这题求无向图的必经点,这个是一个固定套路:首先,一张连通的无向图中,每对点双和点双之间是以一个且仅一个割点连接起来的(如果超过一个就不能是割点了) ...

随机推荐

  1. SQLite剖析之C/C++接口

    前言 SQLite3是SQLite一个全新的版本,它虽然是在SQLite2的代码基础之上开发的,但是使用了和之前的版本不兼容的数据库格式和API.SQLite3是为了满足以下的需求而开发的:支持UTF ...

  2. android之Activity回传数据

    约定:当Activity发生跳转时将原来的Activity成为父Activity,将新出现的Activity成为子Activity. 情景设置 下面是个发短信的Activity 当我们点击图中的+按钮 ...

  3. ElasticSearch入门系列(五)数据

    序言:无论程序如何写,最终都是为了组织数据为我们服务.在实际应用中,并不是所有相同类型的实体的看起来都是一样的.传统上我们使用行和列将数据存储在关系型数据库中相当于使用电子表格,这种固定的存储方式导致 ...

  4. Beta项目冲刺 --第二天

    在几kb的上传速度中苦苦挣扎的程序员... 队伍:F4 成员:031302301 毕容甲 031302302 蔡逸轩 031302430 肖阳 031302418 黄彦宁 会议内容: 1.站立式会议照 ...

  5. Mahout安装与配置

    一.安装mahout 1.下载mahout(mahout-distribution-0.9.tar.gz) http://pan.baidu.com/s/1kUtOMQb 2.解压至指定目录 我平时都 ...

  6. Region-Based Segmentation

    读完10.4 Region-Based Segmentation这一小节, 新get到的且需要留意的知识点: Region Spltting and Merging, quadtrees Waters ...

  7. 【ASP.NET Identity系列教程(三)】Identity高级技术

    注:本文是[ASP.NET Identity系列教程]的第三篇.本系列教程详细.完整.深入地介绍了微软的ASP.NET Identity技术,描述了如何运用ASP.NET Identity实现应用程序 ...

  8. java环境变量设置

    java环境变量设置 1.打开我的电脑--属性--高级--环境变量 2.新建系统变量JAVA_HOME 和CLASSPATH 变量名:JAVA_HOME 变量值:C:\Program Files\Ja ...

  9. ElasticSearch快照备份及恢复

    工作步骤: 1:建立备份快照数据挂载点,即共享文件目录(Shared Filesystem): 2:建立快照仓储repository: 3:建立snapshot快照备份: 4:恢复snapshot快照 ...

  10. java-二维码编写zxing

    zxing 这个是google的 下载地址 http://code.google.com/p/zxing/downloads/list 二维码源码案例 package com.utils; impor ...