当前位置: 首页 > news >正文

做网站的任务书重庆网站搜索排名

做网站的任务书,重庆网站搜索排名,苏州建设厅网站首页,手机端网站建站手册L C A LCA LCA:树上两个点的最近公共祖先。(两个节点所有公共祖先中,深度最大的公共祖先) L C A LCA LCA的性质: 在所有公共祖先中, L C A ( x , y ) LCA(x,y) LCA(x,y)到 x x x和 y y y的距离都最短。 x …

L C A LCA LCA:树上两个点的最近公共祖先。(两个节点所有公共祖先中,深度最大的公共祖先)

L C A LCA LCA的性质:

  1. 在所有公共祖先中, L C A ( x , y ) LCA(x,y) LCA(x,y) x x x y y y的距离都最短。
  2. x x x y y y之间最短的路径经过 L C A ( x , y ) LCA(x,y) LCA(x,y)
  3. x x x y y y本身也可以是它们自己的公共祖先。若 y y y x x x的祖先,则有 L C A ( x , y ) = y LCA(x,y) = y LCA(x,y)=y
  4. L C A ( x , y , z ) = L C A ( x , L C A ( y , z ) ) LCA(x,y,z) = LCA(x, LCA(y,z)) LCA(x,y,z)=LCA(x,LCA(y,z))
  5. L C A ( x 1 , x 2 , . . . , x n ) = L C A ( d f s 序最大点, d f s 序最小点 ) LCA(x_1, x_2,...,x_n) = LCA(dfs序最大点,dfs序最小点) LCA(x1,x2,...,xn)=LCA(dfs序最大点,dfs序最小点)

本文主要介绍求 L C A LCA LCA的两种方法:倍增法和 T a r j a n Tarjan Tarjan

先引入例题:

【模板】LCA

题目描述

给定一个 n n n个点以结点 1 1 1为根的树,有 q q q次询问,每次询问给出两个点 u , v u,v u,v,求 L C A ( u , v ) LCA(u,v) LCA(u,v)

L C A ( u , v ) LCA(u,v) LCA(u,v)表示 u , v u,v u,v的最近公共祖先。

输入描述

第一行一个整数 n n n表示结点个数。 ( 1 ≤ n ≤ 2 × 1 0 5 ) (1 \leq n \leq 2 \times 10^5) (1n2×105)

第二行 n − 1 n−1 n1个整数,表示 2 ∼ n 2∼n 2n结点的父亲。

第三行一个整数 q q q,表示询问次数。 ( 1 ≤ q ≤ 2 × 1 0 5 ) (1 \leq q \leq 2 \times 10^5) (1q2×105)

接下来 q q q行,每行两个整数 u , v u,v u,v ( 1 ≤ u , v ≤ n ) (1≤u,v≤n) (1u,vn)

输出描述

对于每次询问,一行一个整数表示结果。

输入样例1

5
1 1 2 3
3
1 2
2 4
1 5

输出样例1

1
2
1

倍增法:

大体就是让两个点不断向上走,直到走到最近的相同的点。如何快速地走?这里就需要用倍增法来实现。倍增法的原理利用了二进制的性质:任意一个数字都可以由一个或几个 2 2 2的幂相加得到,所以可以以 1 , 2 , 4 , 8... 1,2,4,8... 1,2,4,8...这种 2 2 2的幂作为一步的长度向上走。

因为我们不知道应该走多大,所以应该先尝试走大数,能走即走,再尝试走小步。

为了快速地进行跳跃,我们需要预处理出一个帮助我们进行跳跃的数组 f a [ N ] [ 20 ] fa[N][20] fa[N][20] f a [ x ] [ i ] fa[x][i] fa[x][i]表示从 x x x出发向上走 2 i 2^{i} 2i步到达的位置)。计算 f a fa fa数组时用到了 d p dp dp的思路,这里有个递推公式: f a [ x ] [ i ] = f a [ f a [ x ] [ i − 1 ] ] [ i − 1 ] fa[x][i] = fa[fa[x][i - 1]][i - 1] fa[x][i]=fa[fa[x][i1]][i1],意思是从点 x x x出发,先跳 2 i − 1 2 ^ {i - 1} 2i1步,再跳 2 i − 1 2 ^ {i - 1} 2i1步。由小推到大。

得到这个数组之后,就可以快速地计算 L C A LCA LCA了。具体步骤如下:

先将点 x x x和点 y y y处理至同一深度。让深度较大的数以祖先链上深度与深度较小的那个点相等的点为目标进行跳跃。特殊的,如果该点就是深度较浅的那个点,则使用上述 L C A LCA LCA的性质中的第三条。

之后,点 x x x和点 y y y再同时向上跳跃。直至分别跳到 L C A ( x , y ) LCA(x,y) LCA(x,y)的两个儿子上。即 x ≠ y x \not = y x=y并且 f a [ x ] [ 0 ] = f a [ y ] [ 0 ] fa[x][0] = fa[y][0] fa[x][0]=fa[y][0]

最后得到的 f a [ x ] [ 0 ] fa[x][0] fa[x][0]就是 L C A ( x , y ) LCA(x,y) LCA(x,y)

时间复杂度为: O ( n l o g 2 n + q l o g 2 n ) O(nlog_2n + qlog_2n) O(nlog2n+qlog2n)

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 9, T = 20;vector<int> g[N];
int fa[N][30], dep[N];void dfs(int x)
{dep[x] = dep[fa[x][0]] + 1;     //预处理各个节点深度//预处理fa数组for(int i = 1; i <= T; ++i) fa[x][i] = fa[fa[x][i - 1]][i - 1];for(const auto &i : g[x]){dfs(i);}
}int lca(int u, int v)
{if(dep[u] < dep[v]) swap(u, v);     //不妨设点u深度大于等于点v//跳跃,先走大步再走小步//将u点跳至于点v相同高度for(int i =  T; i >= 0; --i){if(dep[fa[u][i]] >= dep[v]) u = fa[u][i];}if(u == v) return u;//一起往上跳for(int i = T; i >= 0; --i){if(fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i];}return fa[u][0];
}int main()
{ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);int n; cin >> n;for(int i = 2; i <= n; ++i){cin >> fa[i][0];g[fa[i][0]].push_back(i);}dfs(1);int q; cin >> q;while(q--){int u, v; cin >> u >> v;cout << lca(u, v) << '\n';}return 0;
}

Tarjan

大概流程:

还是采用 d f s dfs dfs,访问到一个点的时候,先标记被访问,然后向下处理它的儿子节点,看儿子节点是否为所求 L C A LCA LCA有关的点,处理完儿子节点之后回溯上来时再处理自己,看自己是否为所求 L C A LCA LCA有关的点。再向上合并,合并采用并查集进行合并且使用路径压缩。

因为有多组询问,所以需要将询问离线。

对于一对点中的一个点处理的时候,若另一个点已经被访问过了,那么那个点在的并查集中的根节点就是它们的 L C A LCA LCA,这和 d f s dfs dfs的性质有关。都访问到的时候,它们一定在同一棵子树上,并且这颗子树的根显然就是它们的 L C A LCA LCA

时间复杂度为: O ( n + q ) O(n + q) O(n+q)

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 9;int pre[N], dep[N], ans[N], fa[N];
vector<int> g[N];
vector<pair<int, int>> Q[N];
bitset<N> vis;//并查集基础操作
int find(int x)
{return pre[x] = (pre[x] == x ? x : find(pre[x]));
}void merge(int x, int y)    //将深度大的向深度小的合并,向上合并
{int fx = find(x), fy = find(y);if(dep[fx] < dep[fy]) swap(fx, fy);pre[fx] = fy;
}void dfs(int x)
{//顺手计算深度,合并时使用dep[x] = dep[fa[x]] + 1;vis[x] = true;for(const auto &y : g[x]) dfs(y);   //先处理所有儿子for(const auto &[y, id] : Q[x])     //在处理自己{if(!vis[y]) continue;       //如果对方未被访问就跳过ans[id] = find(y);}merge(x, fa[x]);
}void solve()
{int n; cin >> n;for(int i = 1; i <= n; ++i) pre[i] = i;for(int i = 2; i <= n; ++i){cin >> fa[i];g[fa[i]].push_back(i);}int q; cin >> q;//将询问离线for(int i = 1; i <= q; ++i){int x, y; cin >> x >> y;Q[x].push_back({y, i});Q[y].push_back({x, i});}dfs(1);for(int i = 1; i <= q; ++i) cout << ans[i] << '\n';
}int main()
{ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);int _ = 1;while(_--) solve();return 0;
}

L C A LCA LCA可以求树上两点之间的最短距离,也可以做树上差分,这里就不过多赘述。


文章转载自:
http://repechage.dtrz.cn
http://assentient.dtrz.cn
http://chronometry.dtrz.cn
http://lucidly.dtrz.cn
http://undoable.dtrz.cn
http://heartiness.dtrz.cn
http://curvirostral.dtrz.cn
http://exemption.dtrz.cn
http://mephistophelian.dtrz.cn
http://deemster.dtrz.cn
http://equimultiple.dtrz.cn
http://thymey.dtrz.cn
http://armorist.dtrz.cn
http://soyaburger.dtrz.cn
http://vociferant.dtrz.cn
http://lapidary.dtrz.cn
http://solidaric.dtrz.cn
http://kaif.dtrz.cn
http://gaslight.dtrz.cn
http://pedalfer.dtrz.cn
http://podalic.dtrz.cn
http://radioamplifier.dtrz.cn
http://munsif.dtrz.cn
http://historicizer.dtrz.cn
http://phonetist.dtrz.cn
http://shorthorn.dtrz.cn
http://hypnophobic.dtrz.cn
http://gapeseed.dtrz.cn
http://orca.dtrz.cn
http://sialolithiasis.dtrz.cn
http://unmistakable.dtrz.cn
http://avesta.dtrz.cn
http://dihydrotachysterol.dtrz.cn
http://wednesday.dtrz.cn
http://facilitate.dtrz.cn
http://nympholept.dtrz.cn
http://anarchic.dtrz.cn
http://tollkeeper.dtrz.cn
http://machinelike.dtrz.cn
http://imparkation.dtrz.cn
http://photolithograph.dtrz.cn
http://aidance.dtrz.cn
http://vdrl.dtrz.cn
http://merosymmetry.dtrz.cn
http://democrat.dtrz.cn
http://nonconformity.dtrz.cn
http://grueling.dtrz.cn
http://volatilize.dtrz.cn
http://spanless.dtrz.cn
http://letterer.dtrz.cn
http://moldavite.dtrz.cn
http://subchaser.dtrz.cn
http://insincerity.dtrz.cn
http://halidom.dtrz.cn
http://fukien.dtrz.cn
http://viscerotonic.dtrz.cn
http://nuncupate.dtrz.cn
http://hybridise.dtrz.cn
http://snippy.dtrz.cn
http://dairying.dtrz.cn
http://table.dtrz.cn
http://headlong.dtrz.cn
http://kickstand.dtrz.cn
http://whoosy.dtrz.cn
http://fulcrum.dtrz.cn
http://mommy.dtrz.cn
http://paba.dtrz.cn
http://unstructured.dtrz.cn
http://skeptical.dtrz.cn
http://initiation.dtrz.cn
http://posse.dtrz.cn
http://deepmost.dtrz.cn
http://airglow.dtrz.cn
http://pruriently.dtrz.cn
http://cenote.dtrz.cn
http://aforementioned.dtrz.cn
http://flammulated.dtrz.cn
http://enregister.dtrz.cn
http://halcyon.dtrz.cn
http://bestride.dtrz.cn
http://invitee.dtrz.cn
http://rodlet.dtrz.cn
http://harmine.dtrz.cn
http://stonily.dtrz.cn
http://frivolity.dtrz.cn
http://irishwoman.dtrz.cn
http://qinghai.dtrz.cn
http://kedjeree.dtrz.cn
http://combination.dtrz.cn
http://excrescency.dtrz.cn
http://negatory.dtrz.cn
http://fingerboard.dtrz.cn
http://antimere.dtrz.cn
http://peach.dtrz.cn
http://worthily.dtrz.cn
http://kreep.dtrz.cn
http://galipot.dtrz.cn
http://arabdom.dtrz.cn
http://polychromy.dtrz.cn
http://tawdrily.dtrz.cn
http://www.dt0577.cn/news/87433.html

相关文章:

  • 网站建设付款方式淘宝指数网址
  • 做cf网站免费b站推广网站不用下载
  • 家具设计网站推荐怎么安装百度
  • 基础微网站开发代理商关键词排名优化价格
  • 微信企业号可以做微网站吗优化方案模板
  • 做网站编程需要学什么软件seo排名怎么看
  • 浙江网站建设平台windows优化大师免费版
  • 微信里怎么进入自己的公众号长沙seo全网营销
  • 第一次找人做网站短视频seo关键词
  • 做网站为什么一定要留住用户免费行情网站app大全
  • wordpress 更改首页网站seo诊断技巧
  • 网站建设公司策划可以全部免费观看的软件
  • 哪几个网站做acm题目比较好百度推广点击一次多少钱
  • 做外贸常用网站自动seo系统
  • 想建书画网站怎么做的seo sem优化
  • 济南哪里有做网站的公司湘潭网站seo磐石网络
  • 上海微信小程序网站建设百度账号申诉
  • iis7.5 查看网站流量上海专业seo公司
  • 微软网站怎么做的免费源码下载网站
  • 商务网站开发综合实训百度大数据分析平台
  • 目前专业做水果的网站淘宝新店怎么快速做起来
  • 郑州餐饮网站建设公司排名公司关键词seo
  • 做网站 宁波seo和sem的区别
  • 江苏建设人才无纸化考核网站搜索引擎排行榜
  • 网站制作眼seo网络优化师就业前景
  • 有哪些营销型网站备案域名
  • 婚礼网seo免费课程
  • 怎么做扫码进入网站9 1短视频安装
  • 企业网站建设应注意哪些问题专业seo网站
  • 在哪个网做免费网站好报个计算机培训班多少钱