poj 1300Nearest Common Ancestors

题目链接:http://poj.org/problem?id=1330

题目描述:给一棵有根树,求两点的最近公共祖先(LCA)

还是太弱了,都大三了,才正式学习如果求lca,,,,太弱了

好在这一次几乎把所有的求lca的方法都写了一遍,就当是入门吧。。。

方法一:暴力求解。预处理出 fa[]数组和dep[] 数组,然后就很简单了

方法二:tarjan。这个是一个离线的做法复杂度为O(n+Q)。需要用并查集来维护一下。主要是一个dfs,对于当前节点u,首先,dfs处理它的子孙;然后,查看所有的与当前节点u有关的查询,看另一个节点是否被标记,若被标记,则答案=find_fa(v),否则,不处理;最后,标记当前节点,并与其父节点合并;

方法三:倍增。预处理一个数组anc[i ][j ],表示i 节点向上走2^j次所到达的节点,如果越过根节点,答案就是根节点。剩下的看一下代码吧,想想就明白了!!另外这个做法可以增加节点,但是不能删除节点

方法四:rmq。先求出dfs序,转化成线性后,感觉舒爽多了,数组里面存的是该节点的深度,具体实现,自己想想吧,很巧妙。n个节点的树会转换成2n-1的数组。

方法五:我不太会,利用的是树链的思想。。。(弱渣伤不起。。。)

/*
暴力LCA
*///#pragma comment(linker,"/STACK:102400000,102400000")
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define ll long long
#define db double
#define PB push_back
#define lson k<<1
#define rson k<<1|1
using namespace std;

const int N = 10005;
const int M = N << 1;
int head[N], to[M], next[M],nedge;

void init()
{
    memset(head, -1, sizeof(head));
    nedge = 0;
}

void add(int a, int b)
{
    to[nedge] = b, next[nedge] = head[a], head[a] = nedge++;
}

int fa[N], dep[N];
void get_fa_dep(int k, int dp)
{
    dep[k] = dp;
    for(int i = head[k]; i >= 0; i = next[i])
    {
        fa[to[i]] = k;
        get_fa_dep(to[i], dp + 1);
    }
}

bool mk[N];

int main()
{
#ifdef PKWV
    freopen("in.in", "r", stdin);
#endif // PKWV
    int T;
    scanf("%d",&T);
    while(T--)
    {
        init();
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) mk[i]=false;
        for(int i=1;i<n;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            mk[b]=true;
            add(a,b);
        }
        int root;
        for(int i=1;i<=n;i++) if(!mk[i])
        {
            root=i;
            break;
        }
        fa[root]=0;
        get_fa_dep(root,0);
        int a,b;
        scanf("%d%d",&a,&b);
        while(a!=b)
        {
            if(dep[a]<dep[b]) b=fa[b];
            else if(dep[b]<dep[a]) a=fa[a];
            else if(a!=b) a=fa[a],b=fa[b];
        }
        printf("%d\n",a);
    }
    return 0;
}

/*
tarjan LCA
*/
//#pragma comment(linker,"/STACK:102400000,102400000")
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define ll long long
#define db double
#define PB push_back
#define lson k<<1
#define rson k<<1|1
using namespace std;

const int N = 10005;
const int M = N;

int head[N],to[N],next[N],nedge;
int ind[N],fa[N];
void init()
{
    nedge=0;
    memset(head,-1,sizeof(head));
}

void add(int a,int b)
{
    to[nedge]=b,next[nedge]=head[a],head[a]=nedge++;
}

bool mk[N];

int find_ind(int r)
{
    if(ind[r]==r) return r;
    return ind[r]=find_ind(ind[r]);
}

void unio(int i,int j)
{
    ind[find_ind(j)]=find_ind(i);
}

int ans[10];

bool fl[N];
vector<int> v[N];
void dfs(int k)
{
    for(int i=head[k];i>=0;i=next[i])
    {
        fa[to[i]]=k;
        dfs(to[i]);
    }
    for(int i=0;i<v[k].size();i+=2)
    {
        int ed=v[k][i];
        if(fl[ed])
        {
            ans[v[k][i+1]]=find_ind(ed);
        }
    }
    fl[k]=true;
    unio(fa[k],k);
}

int main()
{
#ifdef PKWV
    freopen("in.in","r",stdin);
#endif // PKWV
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        memset(mk,false,sizeof(mk));
        init();
        for(int i=1;i<n;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            add(a,b);mk[b]=true;
        }
        int root;
        for(int i=1;i<=n;i++) if(!mk[i])
        {
            root=i;
            break;
        }
        for(int i=1;i<=n;i++) v[i].clear();
        int a,b;
        scanf("%d%d",&a,&b);
        v[a].PB(b),v[b].PB(a);
        v[a].PB(0),v[b].PB(0);
        memset(fl,false,sizeof(fl));
        fa[root]=root;
        for(int i=1;i<=n;i++) ind[i]=i;
        dfs(root);
        printf("%d\n",ans[0]);
    }
    return 0;
}

/*
倍增 LCA
*/
//#pragma comment(linker,"/STACK:102400000,102400000")
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define ll long long
#define db double
#define PB push_back
#define lson k<<1
#define rson k<<1|1
using namespace std;

const int N = 10005;
const int LG = 14;
const int M = N;

int head[N],to[M],next[M],nedge;
int up[N][LG],fa[N],root,dep[N];
bool mk[N];

void init()
{
    memset(head,-1,sizeof(head));
    memset(mk,false,sizeof(mk));
    nedge=0;
}

void add(int a,int b)
{
    to[nedge]=b,next[nedge]=head[a],head[a]=nedge++;
}

void dfs(int k,int dp)
{
    up[k][0]=fa[k],dep[k]=dp;
    int i=0;
    while(up[k][i]!=root)
    {
        ++i;
        up[k][i]=up[up[k][i-1]][i-1];
    }
    while((++i)<LG) up[k][i]=root;  /* very important !!! */
    for(i=head[k];i>=0;i=next[i])
    {
        fa[to[i]]=k;
        dfs(to[i],dp+1);
    }
}

void swim(int &x,int h)
{
    for(int i=0;h>0;i++)
    {
        if(h&1) x=up[x][i];
        h>>=1;
    }
}

int LCA(int a,int b)
{
    if(dep[a]<dep[b]) swap(a,b);
    swim(a,dep[a]-dep[b]);
    while(a!=b)
    {
        for(int i=0;;i++)
        {
            if(up[a][i]==up[b][i])
            {
                if(i==0) return up[a][i];
                else {a=up[a][i-1],b=up[b][i-1];break;}
            }
        }
    }
    return a;
}

int main()
{
#ifdef PKWV
    freopen("in.in","r",stdin);
#endif // PKWV
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        init();
        for(int i=1;i<n;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            add(a,b),mk[b]=true;
        }
        for(int i=1;i<=n;i++) if(!mk[i])
        {
            root=i;
            break;
        }
        fa[root]=root;
        dfs(root,0);
        int a,b;
        scanf("%d%d",&a,&b);
        printf("%d\n",LCA(a,b));
    }
    return 0;
}

/*
RMQ LCA
*///#pragma comment(linker,"/STACK:102400000,102400000")
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define ll long long
#define db double
#define PB push_back
#define lson k<<1
#define rson k<<1|1
using namespace std;

const int N = 10005;
const int LG = 15;
const int M = N;

int head[N],to[M],next[M],nedge;

void init()
{
    memset(head,-1,sizeof(head));
    nedge=0;
}

void add(int a,int b)
{
    to[nedge]=b,next[nedge]=head[a],head[a]=nedge++;
}

int first[N],a[N<<1],pt[N<<1],len;
void dfs(int k,int dp)
{
    a[++len]=dp;first[k]=len;pt[len]=k;
    for(int i=head[k];i>=0;i=next[i])
    {
        dfs(to[i],dp+1);
        a[++len]=dp,pt[len]=k;
    }
}

int rmq[N<<1][LG];
void getrmq()
{
    int l=1;
    for(int i=1;i<=len;i++) rmq[i][0]=i;
    for(int i=1;l<=len;i++)
    {
        for(int j=1;j<=len;j++)
        {
            if(j+l<=len&&a[rmq[j][i-1]]>a[rmq[j+l][i-1]])
                rmq[j][i]=rmq[j+l][i-1];
            else rmq[j][i]=rmq[j][i-1];
        }
        l<<=1;
    }
}

int RMQ(int u,int v)
{
    int k=log((long double)(v-u+1))/log(2.0);
    int l=(int)pow((long double)2,k);
    if(a[rmq[u][k]]<a[rmq[v-l+1][k]]) return rmq[u][k];
    else return rmq[v-l+1][k];
}

bool mk[N];
int main()
{
#ifdef PKWV
    freopen("in.in","r",stdin);
#endif // PKWV
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        init();
        memset(mk,false,sizeof(mk));
        for(int i=1;i<n;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);mk[v]=true;
        }
        int root;
        for(int i=1;i<=n;i++) if(!mk[i])
        {
            root=i;
            break;
        }
        len=0;
        dfs(root,0);
        getrmq();
        int u,v;
        scanf("%d%d",&u,&v);
        u=first[u],v=first[v];
        if(u>v) swap(u,v);
        printf("%d\n",pt[RMQ(u,v)]);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章