zoukankan      html  css  js  c++  java
  • tarjian求lca

    看了好多dalao的博客,就总结一下啦ovo

    tarjian算法很是神奇,它的作用是求lca。它是一种离线算法。

    在线是指输入一个询问输出一个结果。

    离线是将询问一次性输入,一起处理。

    tarjan它是将m个询问打乱顺序,在每个结点上挂上它的询问,利用dfs和并查集进行处理。

    对于一个结点u,如果要找(u,v)的lca,u和v的关系分为以下几种情况:

    (1)结点v在u的子树中,那么lca(u,v)=u;

     (2)  结点v不在u的子树中,那么v就在u子结点以外的结点中。v可能在u的爸爸的子树中,那么lca(u,v)=u的爸爸;

    (3)如果v不在u的爸爸的子树中,那么v可能在u的爸爸的爸爸的子树中,lca(u,v)=u的爸爸的爸爸;

    发现找爸爸的过程好像和并查集的操作很像哦.

    【代码】

    #include<bits/stdc++.h>
    using namespace std;
    #define N 10000
    vector<int>vec[N];
    vector<int>que[N];
    int dad[N],far[N],qx[N],qy[N];
    int n,m,x,y,ans[N];
    int f(int x)
    {
        return far[x]==x?x:far[x]=f(far[x]);    
    }
    void dfs(int x)
    {
        far[x]=x;
        for(int i=0;i<vec[x].size();i++)
        {
            if(dad[x]!=vec[x][i])
            {
                dad[vec[x][i]]=x;
                dfs(vec[x][i]);
            }
        }
        for(int i=0;i<que[x].size();i++)
        {
            if(dad[y=qx[que[x][i]]^qy[que[x][i]]]^x)//y是x结点的一个询问;x^x^y=y; 
            {
                ans[que[x][i]]=f(y);
            }
        }
        far[x]=dad[x];
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&x,&y);
            vec[x].push_back(y);
            vec[y].push_back(x);
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&qx[i],&qy[i]);
            que[qx[i]].push_back(i);//在每个结点上挂上它的询问是第几个询问; 
            que[qy[i]].push_back(i);
        }
        dfs(1);
        for(int i=1;i<=m;i++)
        {
            printf("%d ",ans[i]);//每个询问的答案’ 
        }
        return 0;
    }
  • 相关阅读:
    增强资源管理器右键功能,含源代码
    VC中结构体的内存布局
    进程间共享句柄三种方式
    Delphi获取CPU CPUID《转》
    Delphi中判断WebBrowser的页面是否加载完成 《转》
    Delphi 防止程序多次运行《转》
    界面显示后延时运行代码《转》
    界面显示后延时运行代码《转》
    DIV布局-DIV高度不同自动换行并对齐《转》
    Delphi 语句块《LceMeaning》
  • 原文地址:https://www.cnblogs.com/zzyh/p/6812209.html
Copyright © 2011-2022 走看看