码迷,mamicode.com
首页 > 其他好文 > 详细

lca

时间:2016-04-27 00:03:37      阅读:210      评论:0      收藏:0      [点我收藏+]

标签:

讲得不错的

有参考过的

 

poj,1330

最近公共祖先的taijan离线算法,一次性批处理,然后再query

注意建边,注意访问,注意基于dfs,注意寻找根节点,并查集的运用;

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <string>
 5 #include <vector>
 6 
 7 using namespace std;
 8 const int maxn=10005;
 9 
10 int n,u,v;
11 int parent[maxn];
12 
13 struct Edge
14 {
15     bool notroot;
16     bool vis;
17     vector<int> children;
18 };
19 
20 Edge Tree[maxn];
21 
22 
23 int find(int x)
24 {
25     return x==parent[x]?x:parent[x]=find(parent[x]);
26 }
27 
28 void Union(int x,int y)
29 {
30     int px=find(x);
31     int py=find(y);
32     
33     if(px!=py)
34         parent[py]=px;
35 }
36 
37 bool tarjan(int root)
38 {
39     Tree[root].vis=true;
40     
41     if(root==v && Tree[u].vis)
42     {
43         printf("%d\n",find(u));
44         return true;
45     }
46     
47     if(root==u && Tree[v].vis)
48     {
49         printf("%d\n",find(v));
50         return true;
51     }
52     
53     for(int i=0;i<Tree[root].children.size();i++)
54     {
55         if(tarjan(Tree[root].children[i])) return true;
56         Union(root,Tree[root].children[i]);
57     }
58     return false;
59 }
60 
61 void initial()
62 {
63     memset(parent,0,sizeof(parent));
64     memset(Tree,0,sizeof(Tree));
65     
66     scanf("%d",&n);
67     for(int i=1;i<n;i++)
68     {
69         parent[i]=i;
70         scanf("%d%d",&u,&v);
71         Tree[u].children.push_back(v);
72         Tree[v].notroot=1;
73     }
74     parent[n]=n;
75     
76     int root=0;
77     for(int i=1;i<=n;i++)
78     {
79         if(!Tree[i].notroot)
80         {
81             root=i;
82             break;
83         }
84     }
85     scanf("%d%d",&u,&v);
86     tarjan(root);
87 }
88 
89 int main()
90 {
91     int t;
92     scanf("%d",&t);
93     while(t--)
94     {
95         initial();
96     }
97     return 0;
98 }
View Code

 

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <string>
 4 #include <vector>
 5 #include <algorithm>
 6 
 7 using namespace std;
 8 const int maxn=10005;
 9 
10 int n,u,v;
11 struct Node
12 {
13     bool notroot;
14     vector<int> children;
15 };
16 
17 Node Tree[maxn];
18 int N;
19 
20 int find(int r,int lNode,int rNode)
21 {
22     if(!r) return 0;
23     if(r==lNode) return r;
24     if(r==rNode) return r;
25     
26     vector<int> found;
27     
28     for(int i=0;i<Tree[r].children.size();i++)
29     {
30         found.push_back(find(Tree[r].children[i],lNode,rNode));
31     }
32     
33     int u=0,v=0;
34     for(int i=0;i<(int)found.size();i++)
35     {
36         if(u) v=found[i];
37         else u=found[i];
38     }
39     
40     if(v) return r;
41     return u;
42 }
43 
44 void initial()
45 {
46     memset(Tree,0,sizeof(Tree));
47     scanf("%d",&n);
48     for(int i=1;i<n;i++)
49     {
50         scanf("%d%d",&u,&v);
51         Tree[u].children.push_back(v);
52         Tree[v].notroot=1;
53     }
54     
55     int root=0;
56     
57     for(int i=1;i<=n;i++)
58     {
59         if(!Tree[i].notroot)
60         {
61             root=i;
62             break;
63         }
64     }
65     
66     scanf("%d%d",&u,&v);
67     int r=find(root,u,v);
68     printf("%d\n",r);
69 }
70 
71 int main()
72 {
73     int t;
74     scanf("%d",&t);
75     while(t--)
76     {
77         initial();
78     }
79     return 0;
80 }
递归版

 

代码复用技术啊~~~

注意RMQ与lca的相互关系;

定义三个数组:n代表节点数,lca转化为RMQ问题之后,数组长度为n*2+1

E[n*2+2]  第一次被访问和回溯时被访问的节点

D[n*2+2]  记录此节点的深度

R[n*2+2]  记录节点第一访问的下标

dfs:深搜初始化E,D,R的值。

RMQ:求(i,j)上值最小的索引,分成两段区间。

ST:初始化(i,j)区间上值最小的索引

E[ ( RMQ(D,R[i],R[j] ) ] 就求出了最近公共最先,也是一段序列里面最小的数,层次最低。注意:R[i]<R[j]要不然要交换位置

 

技术分享
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <vector>
  4 #include <cmath>
  5 
  6 #define min(seq,a,b) ((seq[a]<seq[b])?(a):(b))
  7 using namespace std;
  8 
  9 const int maxn=10005;
 10 
 11 vector<int> children[maxn];
 12 int notroot[maxn];
 13 int M[2*maxn+5][100];
 14 
 15 template <typename T>
 16 void st(T seq[],int n)
 17 {
 18     memset(M,0,10*maxn*sizeof(int));
 19     int i,j;
 20     for(i=0;i<n;i++)
 21         M[i][0]=i;
 22     
 23     for(j=1;1<<j<=n;j++)
 24         for(i=0;i+(1<<j)-1<n;i++)
 25         {
 26             int m=i+(1<<(j-1));
 27             M[i][j]=min(seq,M[i][j-1],M[m][j-1]);
 28         }
 29 }
 30 
 31 template <typename T>
 32 int RMQ(T seq[],int i,int j)
 33 {
 34     int k=(int)(log(double(j-i+1))/log(2.0));
 35     
 36     int t=min(seq,M[i][k],M[j-(1<<k)+1][k]);
 37     return t;
 38 }
 39 
 40 int E[2*maxn+5];
 41 int R[2*maxn+5];
 42 int D[2*maxn+5];
 43 int p;
 44 
 45 void dfs(int r,int deep)
 46 {
 47     p++;
 48     E[p]=r;
 49     D[p]=deep;
 50     R[r]=p;
 51     
 52     for(int i=0;i<children[r].size();i++)
 53     {
 54         dfs(children[r][i],deep+1);
 55         p++;
 56         E[p]=r;
 57         D[p]=deep;
 58     }
 59 }
 60 
 61 int main()
 62 {
 63     int t;
 64     scanf("%d",&t);
 65     while(t--)
 66     {
 67         int n;
 68         int u,v;
 69         scanf("%d",&n);
 70         
 71         for(int i=0;i<=n;i++)
 72         {
 73             notroot[i]=0;
 74             children[i].clear();
 75         }
 76         
 77         for(int i=1;i<n;i++)
 78         {
 79             scanf("%d%d",&u,&v);
 80             children[u].push_back(v);
 81             notroot[v]=1;
 82         }
 83         
 84         scanf("%d%d",&u,&v);
 85         
 86         int root=0;
 87         for(int i=1;i<=n;i++)
 88             if(!notroot[i])
 89             {
 90                 root=i;
 91                 break;
 92             }
 93         p=0;
 94         dfs(root,0);
 95         st(D,2*n+2);
 96         
 97         if(R[u]<R[v])
 98             printf("%d\n",E[RMQ(D,R[u],R[v])]);
 99         else
100             printf("%d\n",E[RMQ(D,R[v],R[u])]);
101     }
102     return 0;
103 }
RMQ重写了

 

lca

标签:

原文地址:http://www.cnblogs.com/do-it-best/p/5437131.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!