LCA最近公共祖先 線上演算法和離線演算法 模板
原理講解:http://dongxicheng.org/structure/lca-rmq/
線上演算法模板:
[cpp] view plaincopy在CODE上檢視程式碼片派生到我的程式碼片
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f;
const int maxn=111111;
const int maxm=111111;
int n,m;
struct EDGENODE{
int to;
int w;
int next;
};
struct SGRAPH{
int head[maxn];
EDGENODE edges[maxm];
int edge;
void init(){
memset(head,-1,sizeof(head));
edge=0;
}
void addedge(int u,int v,int c){
edges[edge].w=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++;
}
//------------
int d[maxn][20];
//元素從1編號到n
void makeRmqIndex(int A[],int n){
for(int i=1;i<=n;i++) d[i][0]=i;
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
d[i][j] = A[d[i][j-1]] < A[d[i+(1<<(j-1))][j-1]]? d[i][j-1]:d[i+(1<<(j-1))][j-1];
}
int rmqIndex(int L,int R,int A[])
{
int k=0;
while ((1<<(k+1))<=R-L+1) k++;
return A[d[L][k]]<A[d[R-(1<<k)+1][k]]? d[L][k]:d[R-(1<<k)+1][k];
}
//---------------------
int E[maxn*2],R[maxn],D[maxn*2],mn;
void dfs(int u,int p,int d){
E[++mn]=u;
D[mn]=d;
R[u]=mn;
for (int i=head[u];i!=-1;i=edges[i].next){
int v=edges[i].to;
if (v==p) continue;
dfs(v,u,d+1);
E[++mn]=u;
D[mn]=d;
}
}
void LCA_init(){
mn=0;
memset(R,0,sizeof(R));
dfs(1,-1,1);
makeRmqIndex(D,mn);
getd(1,-1,0);
}
int LCA(int u,int v){
if (R[u]>=R[v]) return E[rmqIndex(R[v],R[u],D)];
else return E[rmqIndex(R[u],R[v],D)];
}
//--------------------
int deep[maxn];
void getd(int u,int p,int w){
deep[u]=w;
for (int i=head[u];i!=-1;i=edges[i].next){
int v=edges[i].to;
if (v==p) continue;
getd(v,u,w+edges[i].w);
}
}
int getDis(int u,int v){
int lca=LCA(u,v);
return deep[u]+deep[v]-deep[lca]*2;
}
int done(int x,int y,int z){
int ans=INF,res=0;
int lca1,lca2;
lca1=LCA(x,y);
res=deep[x]+deep[y]-deep[lca1]*2;
lca2=LCA(lca1,z);
res+=deep[lca1]+deep[z]-deep[lca2]*2;
ans=min(ans,res);
lca1=LCA(x,z);
res=deep[x]+deep[z]-deep[lca1]*2;
lca2=LCA(lca1,y);
res+=deep[lca1]+deep[y]-deep[lca2]*2;
ans=min(ans,res);
lca1=LCA(y,z);
res=deep[y]+deep[z]-deep[lca1]*2;
lca2=LCA(lca1,x);
res+=deep[lca1]+deep[x]-deep[lca2]*2;
ans=min(ans,res);
return ans;
}
}solver;
離線求解:
/**
LCA(離線演算法)
主函式除建邊外還應呼叫
init();
dir[1]=0;
tarjan(1);
*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=40010;
struct note
{
int u,v,w,lca,next;
}edge[maxn*2],edge1[805];
int head[maxn],ip,head1[maxn],ip1;///需要建兩次邊。1,該樹的邊2,需要查詢的兩點
int m,n;
int father[maxn],vis[maxn],dir[maxn];
///依次表示u點的祖先、標記是否訪問過,到根節點的距離
void init()
{
memset(vis,0,sizeof(vis));
memset(dir,0,sizeof(dir));
memset(head,-1,sizeof(head));
memset(head1,-1,sizeof(head1));
ip=ip1=0;
}
void addedge(int u,int v,int w)
{
edge[ip].v=v,edge[ip].w=w,edge[ip].next=head[u],head[u]=ip++;
}
void addedge1(int u,int v)
{
edge1[ip1].u=u,edge1[ip1].v=v,edge1[ip1].lca=-1,edge1[ip1].next=head1[u],head1[u]=ip1++;
}
int Find(int x)
{
if(father[x]==x)
return x;
return father[x]=Find(father[x]);
}
void Union(int x,int y)
{
x=Find(x);
y=Find(y);
if(x!=y)
father[y]=x;
}
void tarjan(int u)
{
vis[u]=1;
father[u]=u;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
int w=edge[i].w;
if(!vis[v])
{
dir[v]=dir[u]+w;
tarjan(v);
Union(u,v);
}
}
for(int i=head1[u];i!=-1;i=edge1[i].next)
{
int v=edge1[i].v;
if(vis[v])
{
edge1[i].lca=edge1[i^1].lca=father[Find(v)];
}
}
}
相關文章
- POJ 1330 LCA最近公共祖先 離線tarjan演算法演算法
- 演算法學習筆記(5): 最近公共祖先(LCA)演算法筆記
- 樹上問題/簡單演算法 LCA【最近公共祖先】演算法
- Git 中的演算法-最近公共祖先Git演算法
- 樹上公共祖先(LCA)
- 最近公共祖先
- Google S2 中的四叉樹求 LCA 最近公共祖先Go
- LeetCode——最近公共祖先LeetCode
- 【Lca 離線Tarjan演算法】hdu 2586 How far away ?演算法
- 二叉樹的最近公共祖先二叉樹
- 「學習筆記」tarjan 求最近公共祖先筆記
- 【Lca 線上st演算法】hdu 2586 How far away ?演算法
- 二叉搜尋樹和二叉樹的最近公共祖先二叉樹
- 二叉樹:距離最近的共同祖先二叉樹
- Lca相關演算法演算法
- 236、二叉樹的最近公共祖先 | 演算法(leetcode,附思維導圖 + 全部解法)300題二叉樹演算法LeetCode
- # 劍指 Offer 68 - II. 二叉樹的最近公共祖先二叉樹
- HDU 1330 Nearest Common Ancestors(求兩個點的最近公共祖先)REST
- LeetCode 236. 二叉樹的最近公共祖先 極限效能演算法 比LeetCode 99%還快50倍LeetCode二叉樹演算法
- leetcode 235. 二叉搜尋樹的最近公共祖先LeetCode
- hdu5452 || 瀋陽網路賽1003題 最近公共祖先問題
- 演算法模板演算法
- (117)235. 二叉搜尋樹的最近公共祖先(leetcode)LeetCode
- 演算法:最長公共字首演算法
- 常用演算法模板演算法
- floyed演算法模板演算法
- 【leetcode 簡單】 第六十八題 二叉搜尋樹的最近公共祖先LeetCode
- [譯] Swift 演算法學院 - 最長公共子序列演算法Swift演算法
- 演算法模板整理(一)演算法
- 演算法基礎模板演算法
- 【模板】【字串】KMP演算法字串KMP演算法
- lc235.二叉搜尋樹的最近公共祖先【①分別得到祖先序列,然後比較;②***同時查詢,找出分岔結點】
- 演算法之字串——最長公共字首演算法字串
- 演算法題:最長公共子序列演算法
- 8.3考試總結(NOIP模擬19)[最長不下降子序列·完全揹包問題·最近公共祖先]
- 迭代最近點演算法 Iterative Closest Points演算法
- [演算法筆記]動態規劃之最長公共子串和最長公共子序列演算法筆記動態規劃
- 最長公共子序列與最小編輯距離-你有更快的演算法麼?演算法