LCA模板

本文针对USACO竞赛中奶牛串门问题(Pasture Walking),提供了详细的算法实现过程。采用深度优先搜索(DFS)进行树状结构遍历,并利用二进制跳跃技巧快速查找最近公共祖先(LCA)。适用于理解复杂图论问题及提高算法设计能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码为nkoj1536--【Usaco Oct08 Gold】奶牛串门(Pasture Walking)
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;
int father[10005][50];
int dep[10005];
int n,m=0;
int S;
int root;
struct line{
	int from;
	int to;
	int len;
};
line edge[1000005];
int len[100005];
int last[10005],_next[1000005];
void add_edge(int x,int y,int l){
	m++;
	edge[m].from=x;
	edge[m].to=y;
	edge[m].len=l;
	_next[m]=last[x];
	last[x]=m;
}
bool mark[10005];
void dfs(int x,int fa){
	int i,h,v;
	father[x][0]=fa;
	dep[x]=dep[father[x][0]]+1;
	int k=ceil(log(dep[x])/log(2));
	for(i=1;i<=k;i++){
		father[x][i]=father[father[x][i-1]][i-1];
	}
	for(h=last[x];h;h=_next[h]){
		v=edge[h].to;
		if(v==fa)continue;
		len[v]=len[x]+edge[h].len;
		dfs(v,x);
	}
}
void go_up(int &v,int p){
	int i;
	for(i=0;i<S;i++){
		if(p&(1<<i))v=father[v][i];
	}
}
int lca(int x,int y){
	int i,k;
	if(dep[x]<dep[y])swap(x,y);
	k=dep[x]-dep[y];
	go_up(x,k);
	if(x==y)return x;
	int s=ceil(log(dep[x])/log(2));
	for(i=s;i>=0;i--){
		if(father[x][i]!=father[y][i]){
			x=father[x][i];
			y=father[y][i];
		}
	}
	return father[x][0];
}
int main(){
	int m;
	cin>>n>>m;
	int i,j,k;
	S=ceil(log(n)/log(2));
	for(i=1;i<n;i++){
		int x,y,l;
		scanf("%d%d%d",&x,&y,&l);
		add_edge(x,y,l);
		add_edge(y,x,l);
	}
	dfs(1,0);
	while(m--){
		int x,y,t;
		scanf("%d%d",&x,&y);
		t=lca(x,y);
		printf("%d\n",len[x]+len[y]-2*len[t]);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值