poj 1330 tarjan lca

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

tarjan 求解lca主要利用并差集的想法:首先遍历树,从叶子节点开始向上合并成一棵棵的子树,然后子树并子树,就成了一棵树了。

查找是在合并的时候进行的,exp:u是s,t的lca,先从u节点进入s,把s并到u下面,然后发现t没有被访问,退到u,再进入t,同样把t并到u下面,发现s被访问过了,那么s的lca也就是s,t的lca了,也就是并差集里的f[s]。当然,f[s]会变的:假设当前f[s] = u; f[u] = u; 当u并到v的时候,也就是f[u]=v; 相应的f[s] = v。这也就是tarjan求解lca的关键方法。

 

这个题裸lca,模板直接上。

View Code
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 10005;
struct nd
{
        int to,next;
}edge[maxn*2];
vector<int>qes[maxn];
int f[maxn],in[maxn],vis[maxn],ans[maxn],ecnt,head[maxn],ok;
void add(int s,int t)
{
        edge[ecnt].to = t;
        edge[ecnt].next = head[s];
        head[s] = ecnt++;
}
int Find(int x)
{
        if(x!=f[x]) f[x] = Find(f[x]);
        return f[x];
}

void LCA(int u)
{
        int i;
        if(ok)return;
        ans[u] = u;
        for(i = head[u]; i!=-1; i=edge[i].next)
        {
                LCA(edge[i].to);
                int x = Find(u);
                int y = Find(edge[i].to);
                if(x!=y) f[x] = y;
                ans[Find(u)] = u;
        }
        vis[u] = 1;
        for(i = 0; i < qes[u].size(); ++ i)
        {
                if(vis[qes[u][i]])
                {
                        ok = 1;
                        printf("%d\n",ans[Find(qes[u][i])]);
                        return ;
                }
        }
}
int main()
{
        int cas,n,i,s,t;
        scanf("%d",&cas);
        while(cas--)
        {
                scanf("%d",&n);
                for(i = 0; i <= n; ++ i) f[i] = i;
                memset(vis,0,sizeof(vis));
                memset(in,0,sizeof(in));
                memset(ans,0,sizeof(ans));
                memset(head,-1,sizeof(head));

                ecnt = 0;
                for(i = 1; i < n; ++ i)
                {
                        scanf("%d %d",&s,&t);
                        add(s,t);
                        in[t]++;
                }
                scanf("%d%d",&t,&s);
                qes[t].push_back(s);
                qes[s].push_back(t);
                ok = 0;
                for(int i = 1; i <= n; ++ i)
                        if(!in[i])
                        {
                                LCA(i);
                                break;
                        }
                qes[t].clear();
                qes[s].clear();
        }return 0;
}

 

posted on 2012-06-19 09:58  aigoruan  阅读(244)  评论(0)    收藏  举报

导航