LCA之倍增及ST算法
来源:互联网 发布:mac git 添加忽略文件 编辑:程序博客网 时间:2024/04/29 16:50
倍增算法就是根据一个数的往上2^n个祖先等于这个数往上的第2^n-1个祖先的第2^n-1个祖先,然后就用rmq预处理。
这一步要打深搜。
void dfs (int h ,int deepth){ p [h] = 1 ; for ( int i = Begin [h] ; i ; i = Next[i]){ if ( !p[to[i]] ){ deep[to[i]] = deepth + 1; dp[to[i]] [0] = h;//记录的是to[i]的父亲结点 dfs (to[i] , deep[to[i]]); } }}
再:
void rmq (int cnt){ int m = cnt; cnt = log (cnt) / log (2) ; for(int j = 1 ;j <= cnt ; j ++ ){ for ( int i = 1 ;i <= m ;i ++){ if(dp[i][j - 1] != 0 && dp[dp[i][j-1]][j-1]!=0) dp [i][j] = dp [ dp[i][j - 1] ][j - 1]; } }}
在查找最近公共祖先的时候再先把两个点提到同一深度,此时若处于同一位置,则返回这个位置的节点编号否则,不断的在不超过最近公共祖先的情况下往这个最近公共祖先逼近
int chaxun (int x,int y){ int d1 = deep[x]; int d2 = deep[y]; if( deep[x] < deep[y]){ swap (x,y); swap (d1,d2); } int i; for ( i = 0; (1 << i) <= d1; i ++ ); -- i; int j; for( j = i ;j >= 0 ;j -- ){ if(d1 - (1<<j) >= d2){ x = dp[x][j]; d1 = d1 - (1<<j); } } if ( x == y ) return x; for( j = i ;j >= 0;j --){ if( dp[x][j] != 0 && dp[x][j] != dp[y][j]/*也就是不超过*/){ x = dp[x][j]; y = dp[y][j]; } } return dp[x][0]; //最后返回的是这个比的最近的点的父亲结点的值}
至于st算法就先放段代码吧:
#include<cmath>#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int maxn = 1000100;int Begin [maxn*2], Next[maxn*2],to[maxn*2];int e;bool p[maxn];int root[maxn*2],first[maxn*2],deep[maxn*2];int dp[maxn][49];void add(int x,int y){ to[++e]=y; Next[e]=Begin[x]; Begin[x]=e;}int cnt;void st(int n){ int i,j; for( i = 1;i <= n ;i ++ ){ dp[i][0]=i; } int k = (int) (log((double)(n)) / log(2.0)); for(i = 1 ;i <= k; i ++){ for ( j = 1;j <= n;j ++ ){ if(j + (1<<i-1) > n)continue; if( deep[dp[j][i-1] ] < deep[dp[ j + (1<<i-1) ][i-1]] ) dp[j][i]=dp[j][i-1]; else dp[j][i] = dp[j+ (1<<i-1) ][i - 1]; } }}int rmq( int x,int y ){ if(x>y){ int temp = x; x = y; y = temp; } int k = (int)(log ((double)(y-x+1))/ log(2.0)); int a = dp[x][k]; int b = dp[y-(1<<k)+1][k]; if(deep[a] > deep[b])return root[b]; else return root[a];}void dfs(int h,int deepth){ p[h]=1,root[++cnt]=h,deep[cnt]=deepth,first[h]=cnt; for(int i = Begin[h] ; i ; i = Next[i]){ if( ! p[to[i]] ){ dfs(to[i] , deepth + 1); root[ ++ cnt ] = h; deep[cnt] = deepth ; } }}int main(){ int i,j,k,m,n,x,y; scanf("%d%d%d",&m,&n,&k); for(i=1;i<=m-1;i++){ scanf("%d%d",&x,&y); add(x,y); add(y,x); } dfs(k,1); st(cnt); for( i = 1;i <= n ;i ++ ){ scanf("%d%d",&x,&y); printf("%d\n",rmq(first[x],first[y])); } return 0;}
1 0
- LCA之倍增及ST算法
- LCA之倍增算法模板
- LCA之ST算法模板
- LCA之ST算法模板 poj-1986
- [POJ]1330 Nearest Common Ancestors (LCA,DFS+ST在线算法 || 倍增算法 || Tarjan离线算法)
- LCA倍增算法(模板)
- lca倍增算法
- lca倍增算法模板
- 倍增算法(LCA)
- LCA的倍增算法
- lca倍增算法
- 浅谈算法-简单倍增及st表的应用
- LCA(st算法)
- LCA-ST算法&Tarjan_LCA
- ST算法与LCA
- LCA st算法
- LCA在线算法ST算法
- LCA在线算法ST算法
- axis1实现webservice
- Leetcode Perfect Squares 279
- POJ 3415 Common Substrings 笔记
- WX-组件-基础内容
- OpenGL 入门6
- LCA之倍增及ST算法
- java swing Jtable 排序支持中文
- 安装mysql时的修改初始密码 mac
- 循环语句
- 背包
- 14. Longest Common Prefix**
- 反转字符串的四种方法
- 性能计数器参考
- redis的持久化