- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
最小公共祖先( LCA )问题 poj1330,1986,1470--fuyuchang(cc)internet 大纲 定义 将 LCA 问题转化为 RMQ 问题 RMQ 的一般解法 ±1 RMQ 问题的快速解法 RMQ 的快速解法 LCA – 最小公共祖先 RMQ – 区间最小询问 时间复杂度标记 LCA – 一般的算法 对任意一对结点,分别找出它们到树根的路径,然后在这两条路经中找第一个公共的结点。 复杂度 = LCA普通算法的图 将 LCA 转化为 RMQ 如果有一个复杂度为 的 RMQ解法,那么就存在一个复杂度为 的LCA解法。 变形 – 根据树T构造3个数组 1. E[1..2n-1]:存放从树根开始的Euler遍历所经过的结点编号。 2. L[1..2n-1]:L[i]存放E[i]结点在树T中的深度。 3. P[1..n]: R[i]表示结点i在数组E中第一次出现的下标。 例 计算 LCAT(u,v) Euler 遍历过程中,夹在u和v第一次被访问中间的结点是E[R[u],…,R[v]]。 其中深度最小的结点的下标是 RMQL(R[u],R[v])。 LCAT(u,v)的结果就是 E[RMQL(R[u],R[v])]。 复杂度分析 预处理 数组构造:O(n)。 根据假设,对数组 L 进行预处理:f(2n-1)。 询问处理 三个数组的访问: O(1)。 根据假设,对数组 L 进行RMQ询问处理:g(2n-1)。 总共: RMQ-LCA在线算法部分代码 bool visit[MAXNODE]; int oula[2*MAXNODE],dist[MAXNODE],pos[MAXNODE],minrmq[18][2*MAXNODE],id[MAXNODE]; int n,m; void add(int u, int v, int w) { edge[e].to = v; edge[e].w = w; edge[e].next = head[u]; head[u] = e++; } void init(){ rst(head,-1); rst(visit,false); tmpdfn=0; index=0; e=0; } void dfs(int u){ visit[u]=true; int len; int oulanum=++tmpdfn; oula[++index]=oulanum; pos[u]=index; id[oulanum]=u; for(int i=head[u];i!=-1;i=edge[i].next){ int next=edge[i].to; if(!visit[next]){ //visit[next]=true; dfs(next); oula[++index]=oulanum; } } return ; } RMQ-LCA在线算法部分代码 int getmin(int l, int r){ int limit=(int)(log((r-l+1)*1.0)/log(2.0)); return min(minrmq[limit][l],minrmq[limit][r-(1limit)+1]); } void RMQ(int len,int *oularmq){ int limit,j; limit=(int)(log(len*1.0) / log(2.0)); forle(i,1,len)minrmq[0][i]=oularmq[i]; forle(i,1,limit) for(j=1;(j+(1i))-1=len;j++){ minrmq[i][j]=min(minrmq[i-1][j],minrmq[i-1][j+(1(i-1))]); } } int LCA(int l, int r){ int cc; if(pos[l]pos[r])cc=l,l=r,r=cc; int ans=getmin(pos[l],pos[r]
文档评论(0)