社区讨论
20pts求条
P10289[GESP样题 八级] 小杨的旅游参与者 2已保存回复 2
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @mhizk542
- 此快照首次捕获于
- 2025/11/03 18:17 4 个月前
- 此快照最后确认于
- 2025/11/03 18:17 4 个月前
lca+bfs,rt,悬关
CPP#include<bits/stdc++.h>
using namespace std;
const int N = 200020;
vector<int>e[N];
bool vis[N];
bool t[N];
int fa[N][20];
int dep[N];
int dis[N];
typedef pair<int,int> pii;
#define fi first
#define se second
#define ll long long
int n;
void dfs(int u,int f){
for(auto v:e[u]){
if(v==f)continue;
fa[v][0] = u;
dep[v] = dep[u]+1;
dfs(v,u);
}
}
void init(){
for(int j = 1;j<=19;j++){
for(int i = 1;i+(1<<j)-1<=n;i++){
fa[i][j] = fa[fa[i][j-1]][j-1];
}
}
}
int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
for(int i = 19;i>=0;i--){
if(dep[fa[x][i]]>=dep[y])x = fa[x][i];
}
if(x==y)return x;
for(int i = 19;i>=0;i--){
if(fa[x][i]!=fa[y][i])x = fa[x][i],y = fa[y][i];
}
return fa[x][0];
}
void bfs(){
queue<int>q;
for(int i = 1;i<=n;i++)if(t[i])q.push(i);
while(!q.empty()){
int u = q.front();
q.pop();
if(vis[u])continue;
vis[u] = 1;
for(auto v:e[u]){
if(vis[v])continue;
dis[v] = dis[u]+1;
q.push(v);
}
}
}
int main(){
int k,q;
cin>>n>>k>>q;
//step1:倍增求LCA
//step2:求最近传送门距离
//step3:分讨,取min
//一开始没想出来的原因:没看到是树。。。
//下次要认真读题~
//tips:任意一点为根遍历均可
//18:34开始写代码
//update:一开始疏漏的地方:把所有有传送门的压入队列,bfs打标记,保证不会重复遍历
//k==0要特判
for(int i = 1;i<=n-1;i++){
int u,v;
cin>>u>>v;
e[u].push_back(v);
e[v].push_back(u);
}
for(int i = 1;i<=k;i++){
int u;
cin>>u;
t[u] = 1;
}
dep[1] = 1;
dfs(1,-1);
init();
bfs();
while(q--){
int u,v;
cin>>u>>v;
int s1 = dep[u]+dep[v]-2*dep[lca(u,v)];
int s2 = dis[u]+dis[v];
if(k==0)s2 = 1e9+10;
cout<<min(s1,s2)<<"\n";
}
return 0;
}
HasNoNamekeshuhan
ToastBread
XaoWa118
急!
回复
共 2 条回复,欢迎继续交流。
正在加载回复...