1.最大生成树去除重边,只要最大的边成树
2.LCA查最近公共祖先,然后询问的lca(x,y)=ff,分别从x,y向上找最小边
3.bfs1/dfs1就是2.中向上找的具体实现


cpp
#include<bits/stdc++.h>
using namespace std;
#define N 100011
typedef long long ll;
typedef pair<ll,int> pii;
int n,m,q;
int ff,mi;
int faa[N];
typedef struct edge
{
int v;int w;
} edge;
typedef struct ed
{
int u,v;int w;
} ed;
struct cmp
{
bool operator()(const ed &a,const ed &b)const
{
return a.w<b.w;
}
};
int find(int x)
{
if(faa[x]==x) return x;
return faa[x]=find(faa[x]);
}
priority_queue<ed,vector<ed>,cmp> pq;///克鲁斯卡尔
int x,y;
vector<edge> mp[N];
vector<edge> vp[N];
int fa[N][25];
int d[N];
void bfs1(int x)///bfs1和dfs1一样作用,从下往上找最小边
{
queue<int> q;
q.push(x);
while(q.size())
{
int t=q.front();
q.pop();
if(t==ff) break;
for(int i=0;i<mp[t].size();i++)
{
int v=mp[t][i].v;
if(d[v]<d[t])
{
mi=min(mp[t][i].w,mi);
q.push(v);
}
}
}
}
void dfs1(int x)
{
if(x==ff) return;///很重要,这里要return;停下来
for(int i=0;i<mp[x].size();i++)
{
int v=mp[x][i].v;
if(d[v]<d[x])
{
mi=min(mp[x][i].w,mi);
dfs1(v);
}
}
}
void dfs(int u,int f)///LCA的dfs
{
d[u]=d[f]+1;
fa[u][0]=f;
for(int i=1;i<=19;i++)
{
fa[u][i]=fa[fa[u][i-1]][i-1];
}
for(int i=0;i<mp[u].size();i++)
{
int v=mp[u][i].v;
if(v!=f)
{
dfs(v,u);
}
}
}
int lca(int s,int t)///LCA
{
if(d[s]<d[t]) swap(s,t);
for(int i=19;i>=0;i--)
{
if(d[fa[s][i]]>=d[t])
{
s=fa[s][i];
}
}
if(s==t) return s;
for(int i=19;i>=0;i--)
{
if(fa[s][i]!=fa[t][i])
{
s=fa[s][i];
t=fa[t][i];
}
}
return fa[s][0];
}
int main()
{
ios::sync_with_stdio(0);
cout.tie(0);
cin.tie(0);
cin>>n>>m>>q;
for(int i=1;i<=n;i++) faa[i]=i;
for(int i=0;i<m;i++)
{
int u,v, w;
cin>>u>>v>>w;
pq.push({u,v,w});
vp[u].push_back({v,w});
vp[v].push_back({u,w});
}
while(pq.size())///最大生成树去除重边,只取最大
{
ed e=pq.top();
pq.pop();
if(find(e.u)!=find(e.v))
{
mp[e.u].push_back({e.v,e.w});
mp[e.v].push_back({e.u,e.w});
faa[find(e.u)]=find(e.v);
}
}
dfs(1,0);
for(int i=0;i<q;i++)
{
mi=0x3f3f3f3f;
cin>>x>>y;
ff=lca(x,y);///最近公共祖先
dfs1(x);
dfs1(y);
if(mi>=0x3f3f3f3f) cout<<-1<<endl;///特殊情况
else cout<<mi<<endl;
}
return 0;
}