LCA
Posted smallhester
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LCA相关的知识,希望对你有一定的参考价值。
A - How far away ?
HDU - 2586 题意:给出一棵树,树上的边有权值,查询两个点之间的最短权值和
LCA倍增
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<stack> #include<cstdlib> #include<queue> #include<set> #include<string.h> #include<vector> #include<deque> #include<map> using namespace std; #define INF 0x3f3f3f3f3f3f3f3f #define inf 0x3f3f3f3f #define eps 1e-4 #define bug printf("*********\n") #define debug(x) cout<<#x"=["<<x<<"]" <<endl typedef long long LL; typedef long long ll; const int maxn = 4e4 + 5; const int mod = 998244353; int cnt,DEG = 30; int vis[maxn],head[maxn],dep[maxn],fa[maxn][30],dis[maxn]; //dep深度数组 fa[i][j]表示结点 i 的第2 ^ j个祖先 //dis[i] root到任意的一个i结点的距离 struct EDGE int next,to,v; edge[maxn * 2]; void addedge(int x,int y,int z) edge[++cnt].to = y; edge[cnt].v = z; edge[cnt].next = head[x]; head[x] = cnt; void init() cnt = 0; memset(vis,0,sizeof vis); memset(head,-1,sizeof head); memset(dep,0,sizeof dep); memset(dis,0,sizeof dis); memset(fa,0,sizeof fa); void bfs(int root) queue<int>que; dep[root] = 0; //根节点的深度为0 fa[root][0] = root; que.push(root); while(!que.empty()) int tmp = que.front(); que.pop(); for(int i = 1; i < DEG; i++) fa[tmp][i] = fa[fa[tmp][i - 1]][i - 1]; //tmp这个点的2 ^ i的祖先就是 tmp的 2 ^ (i - 1)的祖先这个点的 2 ^ (i - 1)的祖先 for(int i = head[tmp]; i != -1; i = edge[i].next) int v = edge[i].to; if(v == fa[tmp][0]) continue; dep[v] = dep[tmp] + 1; dis[v] = dis[tmp] + edge[i].v; //dis距离数组的更新 fa[v][0] = tmp; que.push(v); int LCA(int u,int v) if(dep[u] > dep[v]) swap(u,v); //使得v的深度比较大 int hu = dep[u],hv = dep[v],tu = u,tv = v; for(int det = hv - hu, i = 0; det; det >>= 1, i++) if(det & 1) tv = fa[tv][i]; if(tu == tv) return tu; for(int i = DEG - 1; i >= 0; i--) if(fa[tu][i] == fa[tv][i]) continue; tu = fa[tu][i]; tv = fa[tu][i]; return fa[tu][0]; int main() int t; scanf("%d",&t); while (t -- ) init(); int n, m; scanf("%d %d",&n,&m); for(int i = 1; i < n; i++) int u,v,k; scanf("%d %d %d",&u,&v,&k); vis[v] = 1; addedge(u,v,k); addedge(v,u,k); int root; for(int i = 1; i <= n; i++ ) if(vis[i] == 0) root = i; break; bfs(root); for(int i = 1; i <= m; i++) int a,b; scanf("%d %d",&a,&b); int ans = dis[a] + dis[b] - 2 * dis[LCA(a,b)]; printf("%d\n",ans);
以上是关于LCA的主要内容,如果未能解决你的问题,请参考以下文章