Tarjan求lca

https://vjudge.net/problem/POJ-1330

是到水的题,简单点在于其只需求一对lca即可,这是比较简单的。

主要看了以下blog

http://blog.csdn.net/hnust_xiehonghao/article/details/9109295

要点在于

1.用并查集维护。

2.必须是离线的,在线不行。

3.存边可以用vector,比较方便,毕竟边不多。

*4.rank可以实现启发式并查集,可以优化一些时间。

5.anse数组是存祖先的,因为并查集维护,所以只需一步更新即可。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<string>
 6 #include<cstring>
 7 #include<vector>
 8 const int size=10007;
 9 
10 int n,f[size],anse[size],in[size],rank[size],vis[size];
11 using namespace std;
12 vector<int> node[size],que[size];
13 void init();
14 int find(int num);
15 void conbine(int aa,int bb);
16 void lca(int root)
17 {
18     int i,sz;
19     anse[root]=root;
20     sz=node[root].size();
21     for (int i=0;i<sz;i++)
22     {
23     //    if (fa!=node[root][i])
24     //    {
25             lca(node[root][i]);
26             conbine(root,node[root][i]);
27             anse[find(node[root][i])]=root;
28     //    }
29     }
30     vis[root]=1;
31     sz=que[root].size();
32     for (int i=0;i<sz;i++)
33     {
34         if (vis[que[root][i]])
35         {
36             printf("%d
",anse[find(que[root][i])]);
37             return;
38         }
39     }
40 }
41 int main()
42 {
43     int cas,i;
44     scanf("%d",&cas);
45     while (cas--)
46     {
47         int x,y;
48         scanf("%d",&n);
49         init();
50         for (int i=1;i<=n-1;i++)
51         {
52             scanf("%d%d",&x,&y);
53             node[x].push_back(y); 
54             in[y]++;
55         }
56         scanf("%d%d",&x,&y);
57         que[x].push_back(y);
58         que[y].push_back(x);
59         for (y=1;y<=n;y++)
60         {
61             if (in[y]==0) break;
62         }
63         lca(y);
64     }
65 }
66 void init()
67 {
68     int i;
69     for (int i=1;i<=n;i++)
70     {
71         node[i].clear();
72         que[i].clear();
73         f[i]=i;
74         rank[i]=1;
75     }
76     memset(vis,0,sizeof(vis));
77     memset(in,0,sizeof(in));
78     memset(anse,0,sizeof(anse));
79 }
80 int find(int num)
81 {
82     if (f[num]!=num) f[num]=find(f[num]);
83     return f[num];
84 }
85 void conbine(int aa,int bb)
86 {
87     int x=find(aa),y=find(bb);
88     if (x==y) return;
89     if (rank[x]<=rank[y])
90     {
91         f[x]=y;
92         rank[y]+=rank[x];
93     }
94     else
95     {
96         f[y]=x;
97         rank[x]+=rank[y];
98     }
99 }

求在线算法要用倍增lca

原文地址:https://www.cnblogs.com/fengzhiyuan/p/6775445.html