LCA 入门

来源:互联网 发布:矩阵制组织结构的特点 编辑:程序博客网 时间:2024/06/11 02:20

LCA:一个树,给你两个点,问这两个点的最近公共祖先

方法一:dfs,直接先将一个点的祖先求出来,再看另外一个点祖先什么时候与之相遇(用一个标记数组),这样的话,每个询问都是n的时间复杂度
时间复杂度为o(q*n)

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;const int maxn = 10005;int father[maxn],vis[maxn];int main(){    int n,i,j,k,sum,a,b,t,x,y;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        memset(vis,0,sizeof(vis));        memset(father,-1,sizeof(father));        for(i=1;i<n;i++)        {            scanf("%d %d",&x,&y);            father[y]=x;        }        scanf("%d %d",&a,&b);        while(b!=-1)        {            vis[b]=1;            b=father[b];        }        while(!vis[a])            a=father[a];        printf("%d\n",a);    }    return 0;}

法二:tarjian离线法(离线处理,就是将所有m个询问都存起来,然后一起输出)时间复杂度为n+q

int getf(int k){    if(k==f[k]) return k;    else return f[k]=getf(f[k]);}void uin(int a,int b){    int x=getf(a),y=getf(b);    if(x!=y) f[y]=x;}//这里的f和anc数组是不一样的。//最主要的竟然是anc数组。。//因为f中存的是最终的爸爸是谁,anc存的是当前i的上一个爸爸是谁void Tarjan(int u){    anc[u]=u;    for(int i=head[u];i>-1;i=edge[i].pre)    {        node e=edge[i];        if(!vis[e.to])        {            vis[e.to]=1;            Tarjan(e.to);            uin(u,e.to);        }    }    col[u]=1;    for(int i=hq[u];i>-1;i=q[i].pre)    {        node e=q[i];        if(!col[e.to]) continue;        ans[e.id]=d[u]+d[e.to]-2*d[f[getf(e.to)]];//不能直接f[e.to],因为这里确保是最上面的祖先,因为uin的时候f[y]=x,但是以y为爸爸的孩子们的爸爸还没有改到x~    }}

法三:ST在线求LCA
又偷队友代码

#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>#include <iostream>#include <string>#include <vector>using namespace std;const int maxn = 10010;struct node{    int to,pre;}e[maxn*2];int vis[maxn];int dep[maxn];int head[maxn];int dp[maxn][30];int h=0;void init(){    h=0;    memset(e,0,sizeof(e));    memset(vis,0,sizeof(vis));    memset(dep,0,sizeof(dep));    memset(head,-1,sizeof(head));}void add(int from,int to){    e[h].to=to,e[h].pre=head[from];head[from]=h;h++;}void dfs(int u,int fa,int d){    dep[u]=d;    for(int i=head[u];i>-1;i=e[i].pre)    {        node t=e[i];        if(t.to==fa) continue;        dp[t.to][0]=u;        dfs(t.to,u,d+1);    }}void rmp(int n){    for(int i=1;i<20;i++)    {        for(int j=1;j<=n;j++)        {            if((1<<i)>dep[j])continue;            int k=dp[j][i-1];dp[j][i]=dp[k][i-1];        }    }}int query(int x,int y){    if(dep[x]>dep[y]) swap(x,y);    for(int j=20;j>=0&&dep[x]!=dep[y];j--)    {        if(dep[y]-(1<<j)<dep[x]) continue;        y=dp[y][j];    }    if(x==y) return x;    for(int j=20;j>=0;j--)    {        if(dep[x]-(1<<j)<0||dp[x][j]==dp[y][j]) continue;        x=dp[x][j],y=dp[y][j];    }    return dp[x][0];}int main(){    int T;    scanf("%d",&T);    while(T--){        init();        int n;        scanf("%d",&n);        for(int i=1;i<n;i++)        {            int x,y;            scanf("%d %d",&x,&y);            add(x,y),add(y,x);vis[y]=1;        }        for(int i=1;i<=n;i++)        {            if(!vis[i])            {                dfs(i,i,0);                break;            }        }        rmp(n);        int x,y;        scanf("%d %d",&x,&y);        printf("%d\n",query(x,y));    }    return 0;}
原创粉丝点击