1. 程式人生 > >最近公共祖先LCA模板(Tarjan/RMQ)

最近公共祖先LCA模板(Tarjan/RMQ)

Description

Solution

每次想陣列名字都想的異常艱難,於是(因果關係?)這裡存一下模板

離線演算法 Tarjan

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
int father[500005],visited[500005];
int n,m,s; 
int head[500005],cnt=0,head1[500005],cnt1=0;
struct Node{
    int next,to;
}edges[1000005
]; void addedge(int u,int v) { edges[cnt].next=head[u]; head[u]=cnt; edges[cnt++].to=v; } struct Node1{ int next,to,lca; }edges1[1000005]; void addedge1(int u,int v) { edges1[cnt1].next=head1[u]; head1[u]=cnt1; edges1[cnt1++].to=v; } int getfather(int x) { if(father[x]==x)return
x; father[x]=getfather(father[x]); return father[x]; } void _union(int x,int y) { int fx=getfather(x),fy=getfather(y); if(fx!=fy)father[fx]=fy; } void tarjan(int u) { visited[u]=1; father[u]=u; for(int i=head[u];~i;i=edges[i].next) { int t=edges[i].to; if
(!visited[t]) { tarjan(t); _union(t,u); } } for(int i=head1[u];~i;i=edges1[i].next) { int t=edges1[i].to; if(visited[t]) { edges1[i].lca=edges1[i^1].lca=getfather(t); } } } int main() { memset(head,-1,sizeof(head)); memset(head1,-1,sizeof(head1)); scanf("%d%d%d",&n,&m,&s); for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); addedge(x,y); addedge(y,x); } for(int i=1;i<=m;i++) { int a,b; scanf("%d%d",&a,&b); addedge1(a,b); addedge1(b,a); } tarjan(s); for(int i=0;i<2*m;i+=2) { printf("%d\n",edges1[i].lca); } return 0; }

線上演算法 RMQ

這個感覺容易爆記憶體,至少在交洛谷模板題的時候是qwq

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#define Min(a,b) (a<b?a:b)
using namespace std;
int n,m,s;
int head[500005],cnt=0,first[500005],dep[1000005];
int vertex[1000005],rmq[1000005][20],dfs_clock=0;
bool visited[500005];
struct Node{
    int next,to;
}Edges[1000005];
void add(int u,int v)
{
    Edges[cnt].next=head[u];
    head[u]=cnt;
    Edges[cnt].to=v;
    cnt++;
}
void dfs(int u,int depth)
{
    visited[u]=1;
    ++dfs_clock;first[u]=dfs_clock;
    vertex[dfs_clock]=u;
    dep[dfs_clock]=depth;
    for(int i=head[u];~i;i=Edges[i].next)
    {
        int t=Edges[i].to;
        if(!visited[t])
        {
            dfs(t,depth+1);
            vertex[++dfs_clock]=u;
            dep[dfs_clock]=depth;
        }
    }
}
void RMQinit()
{
    for(int i=1;i<=dfs_clock;i++)
    rmq[i][0]=i;
    for(int j=1;(1<<j)<=dfs_clock;j++)
    for(int i=1;i+(1<<j)-1<=dfs_clock;i++)
    {
        if(dep[rmq[i][j-1]]<dep[rmq[i+(1<<(j-1))][j-1]])
        rmq[i][j]=rmq[i][j-1];
        else rmq[i][j]=rmq[i+(1<<(j-1))][j-1];
    }
}
int RMQ(int x,int y)
{
    int l=first[x],r=first[y];
    if(l>r)swap(l,r);
    int k=0;
    while((1<<(k+1))<=r-l+1)k++;
    int a=rmq[l][k],b=rmq[r-(1<<k)+1][k];
    if(dep[a]<dep[b])return a;
    return b;
}
int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d%d%d",&n,&m,&s);
    int x,y;
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    dfs(s,1);
    RMQinit();
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        printf("%d\n",vertex[RMQ(x,y)]);
    }
    return 0;
}