LCA问题的离线处理Tarjan算法模版

Tarjan算法:

http://blog.csdn.net/smallacmer/article/details/7432625

  1 //这个tarjan算法使用了并查集+dfs的操作。中间的那个并查集操作的作用,只是将已经查找过的节点捆成一个集合然后再指向一个公共的祖先。另外,如果要查询LCA(a,b),必须把(a,b)和(b,a)都加入邻接表。
  2 //
  3 //O(n+Q)
  4 
  5 #include <iostream>
  6 #include <cstdio>
  7 #include <cstring>
  8 #include <vector>
  9 
 10 using namespace std;
 11 
 12 #define MAXN 10001
 13 
 14 int n,fa[MAXN];
 15 int rank[MAXN];
 16 int indegree[MAXN];
 17 int vis[MAXN];
 18 vector<int> hash[MAXN],Qes[MAXN];
 19 int ances[MAXN];//祖先
 20 
 21 
 22 void init(int n)
 23 {
 24     for(int i=0;i<=n;i++)
 25     {
 26         fa[i]=i;
 27         rank[i]=0;
 28         indegree[i]=0;
 29         vis[i]=0;
 30         ances[i]=0;
 31         hash[i].clear();
 32         Qes[i].clear();
 33     }
 34 }
 35 
 36 int find(int x)
 37 {
 38     if(x != fa[x])
 39         fa[x]=find(fa[x]);
 40     return fa[x];
 41 }
 42 
 43 void unio(int x,int y)
 44 {
 45     int fx=find(x),fy=find(y);
 46     if(fx==fy) return ;
 47     if(rank[fy]<rank[fx])
 48         fa[fy]=fx;
 49     else
 50     {
 51         fa[fx]=fy;
 52         if(rank[fx]==rank[fy])
 53             rank[fy]++;
 54     }
 55 }
 56 
 57 void Tarjan(int u)
 58 {
 59     ances[u]=u;
 60     int i,size = hash[u].size();
 61     for(i=0;i<size;i++)
 62     {
 63         Tarjan(hash[u][i]);//递归处理儿子
 64         unio(u,hash[u][i]);//将儿子父亲合并,合并时会将儿子的父亲改为u
 65         ances[find(u)]=u;//此时find(u)仍为u,即
 66     }
 67     vis[u]=1;
 68     
 69     //查询
 70     size = Qes[u].size();
 71     for(i=0;i<size;i++)
 72     {
 73         if(vis[Qes[u][i]]==1)//即查询的另一个结点开始已经访问过,当前的u在此回合访问。
 74         {
 75             printf("%d\n",ances[find(Qes[u][i])]);//由于递归,此时还是在u
 76             return;
 77         }
 78     }
 79 }
 80 
 81 int main()
 82 {
 83     int t;
 84     int i,j;
 85     scanf("%d",&t);
 86     while(t--)
 87     {
 88         scanf("%d",&n);
 89         init(n);
 90         int s,d;
 91         for(i=1;i<=n-1;i++)
 92         {
 93             scanf("%d%d",&s,&d);
 94             hash[s].push_back(d);
 95             indegree[d]++;
 96         }
 97         scanf("%d%d",&s,&d);
 98     //    if(s==d)//如果需要计数的时候注意
 99 //            ans[d]++;
100 //        else
101 //        {
102             Qes[s].push_back(d);
103             Qes[d].push_back(s);
104 //        }
105         for(j=1;j<=n;j++)
106         {
107             if(indegree[j]==0)
108             {
109                 Tarjan(j);
110                 break;
111             }
112         }
113     }
114     return 0;
115 }
原文地址:https://www.cnblogs.com/Missa/p/2709749.html