要说搞了这么久比赛还没学过倍增LCA,实在是惭愧。这次驱动我这个懒癌患者学习一下倍增LCA的是这道题——CF609E-Minimum spanning tree for each edge。说起来有时候学习的动力就是这么产生的——Idea我有,工具不会用。
先来扯一扯概念——LCA(Lowest Common Ancestor),最近公共祖先。在一棵有根树中,节点v到根root的路径上所有的节点都叫v的“祖先”,LCA(u,v) 即两个点u,v,距离它们最近的公共祖先,也就是树中“最低”(深度最高,离root最远)的公共祖先。
求LCA有多种算法:
void dfs(int x,int d){
depth[x] = d;
visited[x] = true;
for (vector<int>::iterator it = edge[x].begin();it != edge[x].end();it++)
if (!visited[*it]) dfs(*it,d+1);
}
void lcabinarylifting(int n){
for (int j = 1;j < MAXB;j++)
for (int i = 1;i <= n;i++)
if (~father[i][j-1])
father[i][j] = father[father[i][j-1]][j-1];
}
int findlca(int u,int v){
if (depth[u] < depth[v]) swap(u,v);
for (int b = MAXB-1;b >= 0;b--)
if (depth[father[u][b]] >= depth[v])
u = father[u][b];
if (u == v) return u;
for (int b = MAXB-1;b >= 0;b--)
if (father[u][b] != father[v][b])
u = father[u][b],v = father[v][b];
return father[u][0];
}
POJ1330 模板题,可供测试各种LCA算法。
code 倍增求LCA参考代码。
CF609E 倍增LCA求任意两点路径上的最大边权。
blog entry 题解链接。
Copyright © 2015-2016 zhyack. All Rights Reserved.
如对文章有任何疑问,请移步问题聚集区一览~