• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
TTC84
博客园    首页    新随笔    联系   管理    订阅  订阅
牧场旅行题解

洛谷原题链接:P2912 [USACO08OCT] Pasture Walking G
题意简化:给定一棵树,求Q个询问链(x,y)的长度
容易想到LCA,然后考虑求长度,可以通过倍增法求(x,LCA(x,y)),(y,LCA(x,y)),然后求和即可

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=2000;
int h[N],nx[N],to[N],vl[N];
int deep[N],anst[N][12],st[N][12];
int n,k,idx=1;

void build(int u,int v,int w)
{
	to[idx]=v;
	nx[idx]=h[u];
	vl[idx]=w;
	h[u]=idx++;
}

void dfs(int u,int fa)
{
	deep[u]=deep[fa]+1;
	anst[u][0]=fa;
	for(int i=h[u];i;i=nx[i])
	{
		int v=to[i],w=vl[i];
		if(v==fa) continue;
		st[v][0]=w;
		dfs(v,u);
	}
}

void init()//预处理i的2^n祖先,(i,anst[i][n])的长度 
{
	for(int j=1;(1<<j)<=n;j++)
	{
		for(int i=1;i<=n;i++)
		{
			anst[i][j]=anst[anst[i][j-1]][j-1];
//			cout<<i<<" "<<j<<" "<<anst[i][j]<<endl;
			if(anst[i][j-1])
			st[i][j]=st[anst[i][j-1]][j-1]+st[i][j-1];
		}
	}
}

int lca(int x,int y)
{ 
	if(deep[x]<deep[y]) swap(x,y);
	int d=deep[x]-deep[y];
	for(int j=0;(1<<j)<=d;j++)
	{
		if(d & (1<<j))
		x=anst[x][j];
	}
	if(x==y) return x;
	
	for(int j=11;j>=0;j--)
	{
		if(anst[x][j]!=anst[y][j])
		{
			x=anst[x][j];
			y=anst[y][j];
//			cout<<x<<" "<<y<<endl;
		}
		if(anst[x][0]==anst[y][0]) break;
	}
	return anst[x][0];
}

int quary(int fa,int u)//倍增法求解(fa,u)长度 
{
	int d=deep[u]-deep[fa];
	int res=0;
	for(int j=0;(1<<j)<=d;j++)
	{
		if(d & (1<<j))
		{
			res+=st[u][j];
			u=anst[u][j];
		}
	}
	return res;
}
int main(){
	cin>>n>>k;
	for(int i=1;i<n;i++)
	{
		int x,y,w;
		cin>>x>>y>>w;
		build(x,y,w);
		build(y,x,w);
	}
	dfs(1,0);
	init();
	for(int i=1;i<=k;i++)
	{
		int x,y;
		cin>>x>>y;
		int f=lca(x,y);
		cout<<quary(f,x)+quary(f,y)<<"\n";
	}
} 
posted on 2025-09-29 21:53  TTC_84  阅读(3)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3