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 }

你可能感兴趣的:(tar)