最近公共祖先LCA【模板】
来源:互联网 发布:淘宝企业店铺升级条件 编辑:程序博客网 时间:2024/06/04 23:33
Tarjan-LCA算法:
对于每一点u:
1.建立以u为代表元素的集合。
2.遍历与u相连的节点v,如果没有被访问过,对于v使用Tarjan-LCA算法,结束后,将v的集合并入u的集合。
3.对于与节点u相关的询问(u,v),如果v被访问过,则结果就是v所在集合的所代表的元素。
求(u,v)的最近公共祖先节点,则询问时调用QEdges[k].lca = find(QEdges[k].to);
求(u,v)在树上的距离,Dist(u,v) = Dist(1,u) + Dist(1,v) - 2*Dist( 1,LCA(u,v) ),即u到根结点的距离 + v到根结点的距离 - 2*(u,v)最近公共祖先到根结点的距离,则询问时调用QEdges[k].lca = Dist[u] + Dist[QEdges[k].to] - 2*Dist[find(QEdges[k].to)];
#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>using namespace std;const int MAXN = 80080;const int MAXQ = 20020;int father[MAXN],Head[MAXN],QHead[MAXN],Dist[MAXN];//Head[]和Eges[]用来存储原图;QHead[]和QEdges[]用来存储询问struct EdgeNode{ int to; int next; int lca;}Edges[MAXN],QEdges[MAXN];int find(int x){ if(x != father[x]) father[x] = find(father[x]); return father[x];}bool vis[MAXN];void LCA(int u){ father[u] = u; vis[u] = true; for(int k = Head[u]; k != -1; k = Edges[k].next) { if(!vis[Edges[k].to]) { Dist[Edges[k].to] = Dist[u] + Edges[k].lca; LCA(Edges[k].to); father[Edges[k].to] = u; } } for(int k = QHead[u]; k != -1; k = QEdges[k].next) { if(vis[QEdges[k].to]) { //QEdges[k].lca = find(QEdges[k].to); QEdges[k].lca = Dist[u] + Dist[QEdges[k].to] - 2*Dist[find(QEdges[k].to)]; QEdges[k^1].lca = QEdges[k].lca; } }}int main(){ int N,M,K,u,v,w,a,b; while(~scanf("%d%d",&N,&M)) { memset(father,0,sizeof(father)); memset(Head,-1,sizeof(Head)); memset(QHead,-1,sizeof(QHead)); memset(vis,false,sizeof(vis)); memset(Edges,0,sizeof(Edges)); memset(QEdges,0,sizeof(QEdges)); memset(Dist,0,sizeof(Dist)); int id = 0; for(int i = 0; i < M; ++i)//插入图的M条边 { scanf("%d%d%d",&u,&v,&w); Edges[id].to = v; Edges[id].lca = w; Edges[id].next = Head[u]; Head[u] = id++; Edges[id].to = u; Edges[id].lca = w; Edges[id].next = Head[v]; Head[v] = id++; } //(u,v)和(v,u)都要存,表示双向边 scanf("%d",&K);//K条询问 int iq = 0; for(int i = 0; i < K; ++i) { scanf("%d%d",&a,&b); QEdges[iq].to = b; QEdges[iq].next = QHead[a]; QHead[a] = iq++; QEdges[iq].to = a; QEdges[iq].next = QHead[b]; QHead[b] = iq++; } //同理(u,v)和(v,u)都要存,但是询问时只对一条边回答 LCA(1); //跟结点。 for(int i = 0; i < iq; i+=2) //回答询问 printf("%d\n",QEdges[i].lca); } return 0;}
0 0
- 最近公共祖先LCA【模板】
- [模板]最近公共祖先LCA
- 【模板】lca 最近公共祖先
- LCA----【模板】最近公共祖先(LCA)
- 【模板】最近公共祖先(LCA)
- 【模板】最近公共祖先(LCA)
- P3379 【模板】最近公共祖先(LCA)
- 【模板】【图论】最近公共祖先(LCA)
- 【模板】最近公共祖先(LCA)
- 【LCA倍增模板】【poj1330】最近公共祖先
- 最近公共祖先LCA
- 最近公共祖先(LCA)
- Lca 最近公共祖先
- LCA----最近公共祖先
- LCA (最近公共祖先)
- LCA最近公共祖先
- LCA 最近公共祖先
- 最近公共祖先 LCA
- 203. Remove Linked List Elements
- c++中cstring向char c[1024]转换
- 【MongoDB】Java驱动下,反射实现DAO的写操作
- 深入A*算法
- Linux下安装jdk与tomcat
- 最近公共祖先LCA【模板】
- fsck(file system check)
- 单应矩阵计算 findHomography和getPerspectiveTransform区别
- 版本更新
- ubuntu修改用户名、计算机名、主目录名
- java 初始化数组
- 如何备份linux系统
- 用shell脚本实现杨辉三角的4个实例
- 浩易南:养成不要脸的习惯