标签:
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 }
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 }
标签:
原文地址:http://www.cnblogs.com/do-it-best/p/5437131.html