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;
}


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