zoukankan      html  css  js  c++  java
  • poj 1330 Nearest Common Ancestors

    http://poj.org/problem?id=1330

    这个是tarjian离线的版本:

    对于一个父亲的所有孩子。我们都去递归Lca。如果当前点是要询问的那个两个点中的一个而且另外一个已经访问过了。就输出。

    方法一:Tarjan离线算法
    在学习离线算法的时候先需要先巩固一下深度搜索,并查集
    Tarjan离线算法是基于深度优先搜索的,我们从根开始向下搜索,搜到一个节点的时候首先判断该节点所有子节点是否访问过,如果都已经访问过,则判断该节点是否询问点里面的其中一个,如果是,则判断跟它相对应的那个点是否已经访问过,如果访问过,则他们的最近公共祖先便是已经访问过的那个节点的当前节点,如果另外一个节点没有访问,则继续进行深度搜索。

     1 #include<iostream>
     2 #include<string.h>
     3 #include<algorithm>
     4 #include<stdio.h>
     5 #define maxn 12000
     6 #include<vector>
     7 using namespace std;
     8 int father[maxn];
     9 int  visit[maxn];
    10 int  root[maxn];
    11 vector<int>node[maxn];
    12 int st,en;
    13 int n;
    14 void init()
    15 {
    16     cin>>n;
    17     for(int i=1;i<=n;i++)
    18     {
    19         father[i]=i;
    20         root[i]=1;
    21         visit[i]=0;
    22         node[i].clear();
    23     }
    24     for(int i=1;i<n;i++)
    25     {
    26         int a,b;
    27         cin>>a>>b;
    28         node[a].push_back(b);
    29         root[b]=0;
    30     }
    31     cin>>st>>en;
    32 }
    33 
    34 int find(int a)
    35 {
    36        if(father[a]!=a)
    37        {
    38            father[a]=find(father[a]);
    39        }
    40        return father[a];
    41 }
    42 void Union(int a,int b)
    43 {
    44     int fa=find(a);
    45     int fb=find(b);
    46     if(fa!=fb)
    47     father[fb]=fa;
    48 }
    49 
    50 void Lca(int parent)
    51 {
    52     for(int i=0;i<node[parent].size();i++)
    53     {
    54         Lca(node[parent][i]);
    55         Union(parent,node[parent][i]);
    56     }
    57     visit[parent]=1;
    58     if(parent==st&&visit[en])
    59     {
    60         cout<<find(en)<<endl;
    61         return ;
    62     }
    63     else
    64     if(parent==en&&visit[st])
    65     {
    66         cout<<find(st)<<endl;
    67         return ;
    68     }
    69 }
    70 
    71 int main()
    72 {
    73     int test;
    74     cin>>test;
    75     for(int i=1;i<=test;i++)
    76     {
    77         init();
    78 
    79         for(int i=1;i<=n;i++)
    80             if(root[i])
    81             {
    82 
    83                 Lca(i);
    84                 break;
    85             }
    86     }
    87     //system("pause");
    88     return 0;
    89 }

     这个是在线的版本

    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    #include<algorithm>
    #include<vector>
    #include<math.h>
    #define maxn 10005
    using namespace std;
    vector<int>node[maxn];
    int indegree[maxn];
    int E[maxn*2+2];
    int R[maxn];
    int D[maxn*2+2];
    int dp[maxn*2+2][100];
    int n;
    int st;
    int en;
    int p;
    void init()
    {
        cin>>n;
            for(int i=1;i<=n;i++)
        {
            node[i].clear();
            indegree[i]=0;
            }
        for(int i=1;i<n;i++)
        {
        int a,b;
        cin>>a>>b;
        node[a].push_back(b);
        indegree[b]++;
        }
        p=0;
        cin>>st>>en;
    }
    
    void dfs(int root,int deep)
    {
        p++;
        E[p]=root;
        D[p]=deep;
        R[root]=p;
        for(int i=0;i<node[root].size();i++)
        {
            dfs(node[root][i],deep+1);
            p++;
            E[p]=root;
            D[p]=deep;
        }
    }
    int min(int a,int b)
    {
        return D[a]<D[b]?a:b;
    }
    
    void  Rmq(int a[],int num)
    {
        memset(dp,0,sizeof(dp));
        for(int i=1;i<num;i++)
            dp[i][0]=i;
        int k=log((double)(num-1))/log(2.0);
        for(int j=1;j<=k;j++)
            for(int i=1;i+(1<<j)-1<num;i++)
            {
      dp[i][j]=D[dp[i][j-1]]<D[dp[i+(1<<(j-1))][j-1]]?dp[i][j-1]:dp[i+(1<<(j-1))][j-1];
            }
    }
    
    int Lca(int a[],int st,int en)
    {
       int k=log(double(en-st+1))/log(2.0);
       return D[dp[st][k]]<D[dp[en-(1<<k)+1][k]]?dp[st][k]:dp[en-(1<<k)+1][k];
    }
    int main()
    {
        int test;
        cin>>test;
        for(int i=1;i<=test;i++)
        {
            init();
            int root;
            for(int i=1;i<=n;i++)
                       if(!indegree[i])
            {root=i;break;}
            dfs(root,0);
            Rmq(D,2*n);
    
            if(R[st]<R[en])
                cout<<E[Lca(D,R[st],R[en])]<<endl;
            else
                cout<<E[Lca(D,R[en],R[st])]<<endl;
        }
        system("pause");
        return 0;
    }
  • 相关阅读:
    C#学生管理系统/学习
    ESC socket通信不通问题
    JavaWeb/ No 'Access-Control-Allow-Origin' header is present on the requested resource
    JavaWeb/ forward跳转到jsp页面后出现中文乱码问题
    JavaWeb/ MVC模式的初次实践
    docker搭建常用应用以及遇到的坑
    突验 8 进程通信
    实验七 信号
    实验6进程基础
    实验5 shell脚本编程
  • 原文地址:https://www.cnblogs.com/cs1003/p/2650973.html
Copyright © 2011-2022 走看看