/*********--LCA模板--***************/
//设置好静态参数并构建好图的邻接表,然后调用lca_setquery()设置查询
//最后调用lca_start(),在lca::dfs中的your code处理每次查询
//复杂度O(M+Q)
//表示图的邻接表 #define N 40100
#define MAX_Q 200 struct node
{
int to,next,w;
}edge[*N]; int pre[N],cnt; int ans[MAX_Q]; void add_edge(int u,int v,int w)
{
edge[cnt].w = w;
edge[cnt].to = v;
edge[cnt].next =pre[u];
pre[u] = cnt++;
} struct LCA
{
int ln;//表示图中的点,默认范围为[1,n]
int bin[N],bw[N]; // 并查集 与 bw记录到根节点的深度
struct node1
{
int to,next;
int id;
}edge1[MAX_Q*];
int pre1[N],cnt1;
int lmark[N]; void init(int n)//初始化传入点的个数n
{
ln = n;
cnt1 = ;
memset(pre1,-,sizeof(pre1));
memset(lmark,,sizeof(lmark));
for(int i=;i<=n;i++)
bin[i] = i;
} void add_edge1(int u,int v,int id)
{
edge1[cnt1].id = id;//查询的id
edge1[cnt1].to = v;
edge1[cnt1].next = pre1[u];
pre1[u]=cnt1++;
} int find(int v)
{
if(bin[v]==v) return v;
return bin[v]=find(bin[v]);
} void lca_setquery(int m)
{
//把所有的查询加入
//add_edge1(a,b);
//add_edge1(b,a);
for(int i=;i<m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
add_edge1(a,b,i);
add_edge1(b,a,i);
}
} void dfs(int s,int w,int fa)
{
bw[s]=w;
for(int p=pre[s];p!=-;p=edge[p].next)
{
int v=edge[p].to;
if(v == fa) continue;//不到父亲节点
if(lmark[v]==)
{
//dfs(v,w+1,s);
dfs(v,w+edge[p].w,s);
bin[v]=s;
}
}
lmark[s] = ;
//遍历需要查询的点对
for(int p=pre1[s];p!=-;p=edge1[p].next)
{
int v = edge1[p].to;
if(lmark[v] == )//这个点已经处理过了
{
int x = find(v); //最近公共祖先
int dis = bw[v]-bw[x]+bw[s]-bw[x];//两点之间在树上最近距离(这里默认树边为1)
// your code
//ans[ edge1[p].id ] = dis;
//
}
} } void lca_start()
{
dfs(,,-);//第一个参数表示根节点
} }lca; //给出大小为n的树,查询m次两点最短距离
//int main()
//{
// int T;
// cin>>T;
// while(T--)
// {
// int n,m;
// scanf("%d%d",&n,&m);
// cnt = 0;
// memset(pre,-1,sizeof(pre));
// for(int i=1;i<n;i++)
// {
// int a,b,c;
// scanf("%d%d%d",&a,&b,&c);
// add_edge(a,b,c);
// add_edge(b,a,c);
// }
//
// lca.init(n);
// lca.lca_setquery(m);
// lca.lca_start();
// for(int i=0;i<m;i++) printf("%d\n",ans[i]);
// }
// return 0;
//}

2.LCA 在线建立rmq(nlog(n)) 查询(log(n))

#define N 40040
#define LN 20
struct node
{
int to,next;
}edge[*N]; int cnt,pre[N]; void add_edge(int u,int v)
{
edge[cnt].to = v;
edge[cnt].next = pre[u];
pre[u] = cnt++;
} struct Lca_Online
{
int _n;
int deep[N];
int dp[N][LN];
void _dfs(int s,int fa,int dd)
{
deep[s] = dd;
for(int p=pre[s];p!=-;p=edge[p].next)
{
int v = edge[p].to;
if(v == fa) continue;
_dfs(v,s,dd+);
dp[v][] = s;
}
} void _init()
{
for(int j=;(<<j)<=_n;j++)
{
for(int i=;i<=_n;i++)
{
if(dp[i][j-]!=-) dp[i][j] = dp[ dp[i][j-] ][j-];
}
}
}
void lca_init(int n)
{
_n = n;
memset(dp,-,sizeof(dp));
//_dfs(firstid,-1,0);
_dfs(,-,);
_init();
} int lca_query(int a,int b)
{
if(deep[a]>deep[b]) swap(a,b);
//调整b到a的同一高度
for(int i=LN-;deep[b]>deep[a];i--)
if(deep[b]-(<<i) >= deep[a]) b = dp[b][i];
if(a == b) return a;
for(int i=LN-;i>=;i--)
{
if(dp[a][i]!=dp[b][i]) a = dp[a][i],b = dp[b][i];
}
return dp[a][];
}
}lca; //int d[N];
//int main(int argc, const char * argv[]) {
// int T;
// cin>>T;
// while(T--)
// {
// memset(d,0,sizeof(d));
// cnt = 0;
// memset(pre,-1,sizeof(pre));
// int n;
// scanf("%d",&n);
// for(int i=1;i<n;i++)
// {
// int a,b;
// scanf("%d%d",&a,&b);
// add_edge(a, b);
// add_edge(b, a);
// d[b]++;
// }
// for(int i=1;i<=n;i++)
// {
// if(d[i] == 0) firstid = i;
// }
// int a,b;
// cin>>a>>b;
// lca.lca_init(n);
// printf("%d\n",lca.lca_query(a, b));
// }
// return 0;
//}

LCA模板的更多相关文章

  1. 倍增求lca模板

    倍增求lca模板 https://www.luogu.org/problem/show?pid=3379 #include<cstdio> #include<iostream> ...

  2. HDU 2586——How far away ?——————【LCA模板题】

    How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  3. 算法复习——LCA模板(POJ1330)

    题目: Description A rooted tree is a well-known data structure in computer science and engineering. An ...

  4. hdu 2586 How far away?(LCA模板题+离线tarjan算法)

    How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  5. LCA模板(数剖实现)

    题目链接:https://www.luogu.org/problemnew/show/P3379 题意:LCA模板题. 思路:今天开始学树剖,先拿lca练练.树剖解lca,两次dfs复杂度均为O(n) ...

  6. POJ 1330 Nearest Common Ancestors(LCA模板)

    给定一棵树求任意两个节点的公共祖先 tarjan离线求LCA思想是,先把所有的查询保存起来,然后dfs一遍树的时候在判断.如果当前节点是要求的两个节点当中的一个,那么再判断另外一个是否已经访问过,如果 ...

  7. HDU2586 How far away ?(LCA模板题)

    题目链接:传送门 题意: 给定一棵树,求两个点之间的距离. 分析: LCA 的模板题目 ans = dis[u]+dis[v] - 2*dis[lca(u,v)]; 在线算法:详细解说 传送门 代码例 ...

  8. 最近公共祖先(LCA)模板

    以下转自:https://www.cnblogs.com/JVxie/p/4854719.html 首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖 ...

  9. HDU 2586 How far away ?(LCA模板 近期公共祖先啊)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 Problem Description There are n houses in the vi ...

随机推荐

  1. c#省市联动

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  2. php获取json文件数据并动态修改网站头部文件meta信息 --基于CI框架

    话不多说了.直接开始吧  (如果有中文.请注意json只认utf-8编码) 首先你需要有一个json文件数据 {        "index": {                ...

  3. php编译器

    WordPress http://pan.baidu.com/s/1eQnOnv0 epp3: http://pan.baidu.com/s/1pJKFOD1 配合xampp: http://pan. ...

  4. 【算法题目】包含min函数的栈

    题目来源:<剑指offer>面试题21 题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数.在该栈中,调用min,push以及pop的时间复杂度都是O(1). 分 ...

  5. Linux下缓冲区溢出攻击的原理及对策(转载)

    前言 从逻辑上讲进程的堆栈是由多个堆栈帧构成的,其中每个堆栈帧都对应一个函数调用.当函数调用发生时,新的堆栈帧被压入堆栈:当函数返回时,相应的堆栈帧从堆栈中弹出.尽管堆栈帧结构的引入为在高级语言中实现 ...

  6. 局部内部类访问方法中的局部变量为什么加final

    转载:http://www.cnblogs.com/mjblogs/p/4971630.html 1)从程序设计语言的理论上:局部内部类(即:定义在方法中的内部类),由于本身就是在方法内部(可出现在形 ...

  7. 2016-2017 CT S03E05: Codeforces Trainings Season 3 Episode 5 (2016 Stanford Local Programming Contest, Extended) I

    链接:http://codeforces.com/gym/101116 题意:选六个数,必须出现次数最多,且数字最小,如果出现7优先加入7 解法:排序,出现7优先加入7,最后再将6个数排序 #incl ...

  8. bzoj 3234: [Ahoi2013]立方体

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3234 题意:求长方体交的表面积. 思路:flood-fill const int ...

  9. 【转】Ajax中send方法参数的使用(get/post)

    Ajax中send方法参数的使用 一般情况下,使用Ajax提交的参数多是些简单的字符串,可以直接使用GET方法将要提交的参数写到open方法的url参数中,此时send方法的参数为null. 例如 : ...

  10. 关于socket tcp 断线重连

    这个问题困扰过我几次,都没有来得及研究,今天研究一下. 首先写一个最简易的socket tcp程序,连接成功后再关闭服务器然后再用客户端各种操作看是什么情况 测试表明 (1)客户端已经连接,当服务端关 ...