HDOJ2586 最近公共祖先模板

原題鏈接:HDOJ2586

解析:用樹上倍增法來求LCA

代碼實例:

#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn = 40010;
int f[maxn][20],d[maxn],Dist[maxn];
//依次爲:f[i,k]節點i上升2^k次方的節點,d[i]i的深度,Dist[i]i到樹根的距離 
int deep;//樹的最大深度 
vector<int> G[maxn];//來存放每個點相連的邊的編號 
struct Edge{
	int from,to,dist;
};
vector<Edge> edges;
void add_edge(int from,int to,int dist){//如果無向邊壓入兩次 
	edges.push_back(Edge{from,to,dist});
	int m = edges.size()-1;
	G[from].push_back(m);
}
void bfs(){//預處理 
	queue<int> q;
	q.push(1);
	d[1] = 1;
	while(!q.empty()){
		int x = q.front();
		q.pop();	
		for(int i = 0;i < G[x].size();i++){
			Edge& e = edges[G[x][i]];
			if(d[e.to])	continue;
			d[e.to] = d[x] + 1;
			Dist[e.to] = Dist[x] + e.dist;
			f[e.to][0] = x;
			for(int j = 1;j < deep;j++)
				f[e.to][j] = f[f[e.to][j-1]][j-1];
				//e.to向上走2^k步到達的節點等於e.to向上走2^(k-1)步到達的節點再向上走2^(k-1)步 
			q.push(e.to); 
		}
	}
}
int lca(int x,int y){
	if(d[y] < d[x])	swap(x,y); 
	for(int i = deep;i >= 0;i--)//將y上升至和x同一高度 
		if(d[f[y][i]] >= d[x])	y = f[y][i];
	if(x == y)	return x;
	for(int i = deep;i >= 0;i--)//將x和y同時上升2^i個高度,如果相等,說明f[x][0]爲答案 
		if(f[x][i] != f[y][i])	x = f[x][i],y = f[y][i];
	return f[x][0];
		
}
void init(int n){
	memset(f,0,sizeof f);
	memset(d,0,sizeof d);
	memset(Dist,0,sizeof Dist);
	edges.clear();
	for(int i = 0;i <= n;i++)	G[i].clear();
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--){
		int n,m;
		scanf("%d%d",&n,&m);
		init(n);
		deep = (int)(log(n)/log(2))+1;
	
		for(int i = 0;i < n-1;i++){
			int x,y,z;
			scanf("%d%d%d",&x,&y,&z);
			add_edge(x,y,z);
			add_edge(y,x,z);
		}
		bfs();
		for(int i = 0;i < m;i++){
			int x,y;
			scanf("%d%d",&x,&y);
			printf("%d\n",Dist[x]+Dist[y]- 2*Dist[lca(x,y)]);
		}
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章