1. 程式人生 > >倍增LCA 板子題 還是 hdu 2856 how far away 【個人感覺無比詳細】 > <

倍增LCA 板子題 還是 hdu 2856 how far away 【個人感覺無比詳細】 > <

之前擼了一發離線的lca 就是tarjan演算法

這次來一發倍增lca

對於兩個節點的lca   這兩個節點要到同層 再跳躍倍增找到祖先

其本質是跳躍 2^i ==2^(i-1)+2^(i-1)

文字表述是我跳到八代祖先 我就先跳到四代祖先 再跳四代祖先

#include<cstring>
#include<cstdio>
#include<vector>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;

const int maxn=40020;
int dis[maxn];//根到子節點的距離    
int depth[maxn];//每個節點的深度
int p[maxn][20];
int n,m;

struct node
{
	int to,value;
};

vector<node> vec[maxn];

void dfs(int u,int step,int father)
{
	//標個粑粑 順便把節點搜尋出來 
	depth[u]=step;
	p[u][0]=father;
	for(int i=0;i<vec[u].size();i++)
	{
		int v=vec[u][i].to;
		int w=vec[u][i].value;
		if(v!=father)
		{
			dis[v]=dis[u]+w;
			dfs(v,step+1,u);
		}
	}
}

void init_f()
{
	for(int i=1;(1<<i)<=n;++i)//初始化到最壞情況 就是所有子節點都在一側
	{
		for(int j=1;j<=n;++j)
		{
			p[j][i]=p[p[j][i-1]][i-1];
		}
	}
}

/*int lca(int u,int v)
{
	if(u==v) return u;
	if(depth[u]<depth[v]) swap(u,v);
	int d=depth[u]-depth[v];
	for(int i=0;(1<<i)<=d;i++)
	{
		if((1<<i)&d) u=p[u][i];
	}
	for(int i=(int)log2(n);i>=0;i--)
	{
		if(p[u][i]!=p[v][i])
		{
			u=p[u][i];
			v=p[v][i];
		}
	}
	return p[u][0];
}*/
int lca(int u,int v)
{
    if(depth[u]<depth[v]) swap(u,v);
    int d=depth[u]-depth[v];
    for(int j=19;j>=0;--j){    
        if((1<<j)&d) //當d為3(11) 1<<j 為 10 就可以跳此時j為1. 當j為0時 1<<j 為1 就總共跳了3次
		//Q:為毛不會重複跳躍同樣的次數 如:當d為(1xx)時,跳6下(110) 和4下(100)都會進入if啊?
		//A:他這是跳完之後就直接把這個二進位制位直接移走了呀 所以不會重複跳 
            u=p[u][j];      
    }
    /*
	之前這一段 我想的跳到同層的操作是
	for(int i=0;(1<<i)<=d;i++)
	if((1<<j)&d)
	u=p[u][j];
	但其實是錯誤的
	從1開始起跳
	假如我要跳到上八代祖先是永遠也不可能實現的
	因為它是這樣跳的嘛 1 2 4 8
	奇數只有一個 根本湊不到8 
	*/  
    if(u==v){   
        return u;
    }
    for(int i=(int)log2(n);i>=0;--i){//這裡的logn是最壞情況 即所有元素都在樹的一側 
        if(p[u][i]!=p[v][i]){   //所以直接從高位起跳 加速 
        //Q:跳過頭了咋辦
		//A:跳過頭的元素值是相同的  進不了if 所有u v不會更新 
		//Q:敲裡嗎 為毛元素是相同的 博主你快講清楚
		//A:init_f裡 假如設根節點為第0層 第一層的節點假如跳兩下就過頭了 
		//那麼p[x][1]=p[p[x][0]][0] 其值還是根節點的父親 無論跳多少次都是根節點的父親 
            u=p[u][i];
            v=p[v][i];
        //所以u v的值始終不同 但會隨著程式的執行接近lca    
        }
    }
    return p[u][0];    
}
 

int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++)
		{
			vec[i].clear();
		}
		for(int i=0;i<n-1;i++)
		{
			node tem;
			int u,v,w;
			scanf("%d%d%d",&u,&v,&w);
			tem.to=v;
			tem.value=w;
			vec[u].push_back(tem);
			tem.to=u;
			vec[v].push_back(tem); 
		}
		dis[1]=0;
		dfs(1,0,0);
		init_f();
		for(int i=1;i<=m;i++)
		{
			int u,v;
			scanf("%d%d",&u,&v);
			int ans=dis[u]+dis[v]-2*dis[lca(u,v)];
			printf("%d\n",ans);
		}
	}
}