最近公共祖先(LCA)---倍增法
2017-01-12 22:03
387 查看
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<algorithm> #define Size 1000000 using namespace std; int be[Size],ne[Size],to[Size],e; void add(int x,int y){to[++e]=y;ne[e]=be[x];be[x]=e;} int deep[Size]; int fa[Size>>1][20]; bool vis[Size]; int read(){ int x=0; char ch=getchar(); while(ch<'0' || ch>'9')ch=getchar(); while(ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } return x; } void dfs(int x){ vis[x]=1; for(int i=be[x];i;i=ne[i]){ if(!vis[to[i]]){ fa[to[i]][0]=x;//标记上一个为父亲节点 deep[to[i]]=deep[x]+1; dfs(to[i]); } } } void build(int n){ int k=log(n)/log(2); for(int i=1;i<=k;i++) for(int j=1;j<=n;j++) if(fa[j][i-1]!=0 && fa[fa[j][i-1]][i-1]!=0) fa[j][i]=fa[fa[j][i-1]][i-1]; } int query(int x,int y){ if(deep[x]<deep[y])swap(x,y);//把x作为深度较大的点 int t; for(t=0;(1<<t)<=deep[x];t++); t--; for(int j=t;j>=0;j--) if(deep[x]-(1<<j)>=deep[y]) x=fa[x][j]; if(x==y)return x; for(int j=t;j>=0;j--){ if(fa[x][j]!=0 && fa[x][j]!=fa[y][j]){//不能为同一个点 x=fa[x][j]; y=fa[y][j]; } } return fa[x][0]; } int main(){ int n,m,s;//n个点,m个边,以s点为根节点 n=read();m=read();s=read(); for(int i=1;i<n;i++){ int x,y; x=read();y=read(); add(x,y);add(y,x); } deep[s]=1; dfs(s); build(n); for(int i=1;i<=m;i++){ int x,y; x=read();y=read(); printf("%d\n",query(x,y)); } return 0; } /* 5 5 4 3 1 2 4 5 1 1 4 2 4 3 2 3 5 1 2 4 5 4 4 1 4 4 */
相关文章推荐
- 【讲解+模板】最近公共祖先(LCA)(倍增)
- HDU6115 Factory(最近公共祖先lca,在线倍增,暴力)
- LCA(最近公共祖先)倍增法实现
- HDU - 4547 倍增法求最近公共祖先(LCA)
- 用“倍增法”求最近公共祖先(LCA)
- 【LCA倍增模板】【poj1330】最近公共祖先
- poj 1986 最近公共祖先 (lca 倍增)
- 求LCA最近公共祖先的在线倍增算法模板_C++
- LCA(最近公共祖先)倍增算法
- 最近公共祖先(LCA):tarjan与倍增
- POJ1330 Nearest Common Ancestors(在线倍增,离线Tarjan,最近公共祖先LCA)
- 最近公共祖先 LCA 倍增+Tarjan实现
- [置顶] 倍增LCA(最近公共祖先)算法详解
- LCA 在线倍增法 求最近公共祖先
- 最近公共祖先LCA倍增算法
- lca(最近公共祖先)倍增模板【pascal】
- 洛谷 P3379 【模板】最近公共祖先(LCA) (在线倍增+离线Tarjan)
- 最近公共祖先:LCA及其用倍增实现 +POJ1986
- LCA 在线倍增法 求最近公共祖先
- 树上倍增求LCA(最近公共祖先)