洛谷 P10289 [GESP样题 八级] 小杨的旅游 题解
题目简述
给定一棵树,节点之间的距离为
题目分析
首先考虑没有传送门,我们可以直接求两个点的 LCA,再用高度容斥计算即可。
如果有传送门,那么有用与不用两种选择,如果用的话,那么最优的方法一定是
代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,k,Q,deep[N],fa[N][40],dis[N];
vector<int> G[N];
queue<int> q;
void dfs(int u,int father)
{
deep[u]=deep[father]+1;
fa[u][0]=father;
for(int i=1;i<=30;i++)
fa[u][i]=fa[fa[u][i-1]][i-1];
for(int v:G[u])
if(v!=father) dfs(v,u);
return;
}
int lca(int u,int v)
{
if(deep[u]<deep[v])
swap(u,v);
int temp=deep[u]-deep[v];
for(int i=0;i<=30;i++)
if(temp>>i&1)
u=fa[u][i];
if(u==v) return u;
for(int i=30;i>=0;i--)
if(fa[u][i]!=fa[v][i])
u=fa[u][i],v=fa[v][i];
return fa[u][0];
}
void bfs()
{
while(!q.empty())
{
int u=q.front();q.pop();
for(int v:G[u])
if(dis[v]==dis[0])
dis[v]=dis[u]+1,q.push(v);
}
return;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>k>>Q;
memset(dis,0x3f,sizeof dis);
for(int x=0,y=0,i=1;i<n;i++)
{
cin>>x>>y;
G[x].push_back(y);
G[y].push_back(x);
}
dfs(1,0);
for(int x=0,i=1;i<=k;i++)
cin>>x,q.push(x),dis[x]=0;
bfs();
for(int x=0,y=0,i=1;i<=Q;i++)
cin>>x>>y,cout<<min(dis[x]+dis[y],deep[x]+deep[y]-2*deep[lca(x,y)])<<"\n";
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】