feat(P1967): 添加LCA查询功能并优化图结构处理

实现基于倍增法的LCA查询功能,用于计算图中两点间最小边权
- 添加dpth、fth和cost数组用于存储深度、父节点和路径最小权值
- 新增dfs函数初始化上述数组
- 实现lca函数查询两点间最小边权
- 修改主函数处理查询请求并优化并查集初始化
- 移除调试代码并添加必要头文件
This commit is contained in:
Zengtudor 2025-09-02 12:24:08 +08:00
parent 727facbee0
commit 8f654d7c2d

View File

@ -1,9 +1,11 @@
#include <algorithm>
#include <cstdint> #include <cstdint>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <ios> #include <ios>
#include <iostream> #include <iostream>
#include <queue> #include <queue>
#include <utility>
#include <vector> #include <vector>
using ll = int64_t; using ll = int64_t;
@ -23,9 +25,11 @@ struct XYZ{
} }
}; };
ll n,m; const ll maxlog = 15, inf=1e9;
ll n,m,q;
std::vector<std::vector<Edge>> edg; std::vector<std::vector<Edge>> edg;
std::vector<ll> unf; std::vector<ll> unf, dpth;
std::vector<std::vector<ll>> fth,cost;
std::priority_queue<XYZ> pq; std::priority_queue<XYZ> pq;
ll mergednum = 0; ll mergednum = 0;
@ -42,6 +46,42 @@ static inline bool ismerged(ll a,ll b){
return find(a)==find(b); return find(a)==find(b);
} }
static inline void dfs(ll f,ll cur){
dpth[cur]=dpth[f]+1;
fth[cur][0]=f;
for(ll i=1;i<=maxlog;i++){
fth[cur][i]=fth[fth[cur][i-1]][i-1];
cost[cur][i]=std::min(cost[fth[cur][i-1]][i-1],cost[cur][i-1]);
}
for(auto nxt:edg[cur]){
if(nxt.to==f)continue;
cost[nxt.to][0]=nxt.w;
dfs(cur,nxt.to);
}
}
static inline ll lca(ll a,ll b){
if(dpth[a]>dpth[b])std::swap(a,b);
// ll tmp = dpth[b]-dpth[1],ans=0;错误
ll tmp = dpth[b]-dpth[a],ans=inf;
for(ll j=0;tmp;j++,tmp>>=1){
if(tmp&1){
ans=std::min(ans,cost[b][j]);
b=fth[b][j]; // 注意在if里面
}
}
if(a==b)return ans;
for(ll j=maxlog;j>=0 && a!=b;j--){
if(fth[a][j]!=fth[b][j]){
ans=std::min({ans,cost[a][j],cost[b][j]});
a=fth[a][j];
b=fth[b][j];
}
}
ans=std::min({ans,cost[a][0],cost[b][0]});
return ans;
}
int main(){ int main(){
std::ios_base::sync_with_stdio(false); std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr); std::cin.tie(nullptr);
@ -50,8 +90,15 @@ int main(){
edg.resize(n+1); edg.resize(n+1);
unf.resize(n+1); unf.resize(n+1);
fth.resize(n+1,std::vector<ll>(maxlog+1));
cost.resize(n+1,std::vector<ll>(maxlog+1,inf));
dpth.resize(n+1);
for(ll i=1;i<=n;i++){ for(ll i=1;i<=n;i++){
unf[i]=i;
}
for(ll i=1;i<=m;i++){
ll x,y,z; ll x,y,z;
std::cin>>x>>y>>z; std::cin>>x>>y>>z;
pq.emplace(x,y,z); pq.emplace(x,y,z);
@ -67,12 +114,26 @@ int main(){
mergednum++; mergednum++;
} }
for(ll u=1;u<=n;u++){ // for(ll u=1;u<=n;u++){
for(auto [v,w]:edg[u]){ // for(auto [v,w]:edg[u]){
char buff[128]; // printf("point %lld to %lld weight %lld\n",u,v,w);
memset(buff, 0, sizeof(buff)); // }
sprintf(buff,"point %lld to %lld weight %lld\n",u,v,w); // }
std::cout<<buff;
for(ll i=1;i<=n;i++){
if(dpth[i]==0){
dpth[0]=0;
dfs(0,i);
} }
} }
std::cin>>q;
for(ll i=1;i<=q;i++){
ll a,b;
std::cin>>a>>b;
if (!ismerged(a, b)) {
std::cout<<"-1\n";
continue;
}
std::cout<<lca(a,b)<<'\n';
}
} }