zoukankan      html  css  js  c++  java
  • 【补】[LCA]倍增版LCA

    咕咕咕
    blog密码差点忘了
    NOIP之前坑还是要填的
    之后。。肯能就退役了wwwww

    LCA

    众所周知, LCA有许多的求法(比如暴力)
    对于一个静态的图,我们可以用RMQ,倍增等解决
    好像动态图能用LCT做???

    先说倍增

    倍增,意思是成倍的增加增长;成倍地增长。(来源:百度百科)
    像ST表一样,用一个数组下标表示 (2^j) 步后的父亲节点是什么

    怎么用来求LCA?

    先来说说任意两个节点的位置关系和他们的LCA的关系

    先来简单的:3和10(同深度,LCA为根节点)

    可以直接看出LCA为1
    通过前面倍增记录的父亲节点不断向上跳,跳到相同时出现LCA

    但是事情是不会这样简单的——鲁迅

    6和9(同深度,LCA不是根节点)

    这次也可以直接看出LCA为8
    然而可以跳到两者相同吗??
    并不能,因为那样跳很容易会跳到2,而且不确定能否回去
    所以我们要跳到两者最后不同的父节点上,查出任意一个的父节点得到答案

    5和9(深度不同)

    只有深度相同的时候我们才能一起往上跳,所以现将较深的点向上跳到一样深度的时候再做第二条

    2和9(LCA为其中一个点)

    这次我们在将较深的点往上跳的时候会发现两个点重合了,所以要在一起往上跳之前判断是否在一个点上

    代码(luoguP3379)

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int MAXN=7500011;
    const int MLOG=log2(7500000)+1;
    int fa[MAXN][30];
    int dep[MAXN];
    struct EDGE {
    	int v,nxt;
    }edge[MAXN];
    int head[MAXN];
    int ecnt;
    void addedge(int u,int v) {
    	edge[++ecnt].nxt=head[u];
    	edge[ecnt].v=v;
    	head[u]=ecnt;
    }
    void dfs(int u,int nowdep) {
    	dep[u]=nowdep;
    	for(int i=head[u]; i; i=edge[i].nxt) {
    		int v=edge[i].v;
    		if(!dep[v]) {
    			fa[v][0]=u;
    			dfs(v,nowdep+1);
    		}
    	}
    }
    
    int LCA(int a,int b) {
    	if(dep[a]<dep[b])swap(a,b);
    	for(int j=MLOG; j>=0; j--) {
    		if(dep[a]-(1<<j)>=dep[b])a=fa[a][j];
    	}
    	if(a!=b) {
    		for(int j=MLOG; j>=0; j--) {
    			if(fa[a][j]!=fa[b][j]) {
    				a=fa[a][j];
    				b=fa[b][j];
    			}
    		}
    		a=fa[a][0];
    	}
    	return a;
    }
    
    int main() {
    	int n,m,s;
    	scanf("%d %d %d",&n,&m,&s);
    	for(int i=1; i<n; i++) {
    		int u,v;
    		scanf("%d %d",&u,&v);
    		addedge(u,v);
    		addedge(v,u);
    	}
    	dfs(s,1);
    	for(int j=1; j<=MLOG; j++) {
    		for(int i=1; i<=n; i++) {
    			fa[i][j]=fa[fa[i][j-1]][j-1];
    		}
    	}
    	for(int i=1; i<=m; i++) {
    		int x,y;
    		scanf("%d %d",&x,&y);
    		printf("%d
    ",LCA(x,y));
    	}
    	return 0;
    }
    
  • 相关阅读:
    Effective Java 19 Use interfaces only to define types
    Effective Java 18 Prefer interfaces to abstract classes
    Effective Java 17 Design and document for inheritance or else prohibit it
    Effective Java 16 Favor composition over inheritance
    Effective Java 15 Minimize mutability
    Effective Java 14 In public classes, use accessor methods, not public fields
    Effective Java 13 Minimize the accessibility of classes and members
    Effective Java 12 Consider implementing Comparable
    sencha touch SortableList 的使用
    sencha touch dataview 中添加 button 等复杂布局并添加监听事件
  • 原文地址:https://www.cnblogs.com/shulker/p/9909252.html
Copyright © 2011-2022 走看看