题目链接
跑一遍最大生成树,把选出来的边连双向边建树,树上跑lca时加一个容量cap[i][j],表示i点向上跳2^j路径最小值
bfs要判重啊啊啊啊啊啊……因为没判重T过好几次了,不长记性
(注释部分读入挂加了直接WA……不知道为什么,太弱了没看出来,有大佬看出来了请讲一下)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
using namespace std;
#define INF 0x3f3f3f3f
#define _rep(i,a,b) for(int i=(a);i<=(b);i++)
#define _for(i,a,b) for(int i=(a);i<(b);i++)
typedef long long ll;
const int N=1e4+10;
const int M=5e4+10;
const int DEP=20;
/*const int BUF=40000000;
char Buf[BUF],*buf=Buf;
const int OUT=20000000;
char Out[OUT],*ou=Out;int Outn[30],Outcnt;
inline void write(int x){
if(!x)*ou++=48;
else{
for(Outcnt=0;x;x/=10)Outn[++Outcnt]=x%10+48;
while(Outcnt)*ou++=Outn[Outcnt--];
}
}
inline void writell(ll x){
if(!x)*ou++=48;
else{
for(Outcnt=0;x;x/=10)Outn[++Outcnt]=x%10+48;
while(Outcnt)*ou++=Outn[Outcnt--];
}
}
inline void writechar(char x){*ou++=x;}
inline void writeln(){*ou++='\n';}
inline void read(int&a){for(a=0;*buf<48;buf++);while(*buf>47)a=a*10+*buf++-48;}
*/int n,m,q;
int head[N],tot,newtot,newhead[N];
struct Edge{
int u,v,w,nx;
bool operator<(const Edge&rhs)const{
return w>rhs.w;}
}edge[M<<1],newedge[M<<1];
inline void addedge(int u,int v,int w)
{
edge[tot].u=u;
edge[tot].v=v;
edge[tot].w=w;
edge[tot].nx=head[u];
head[u]=tot++;
}
inline void addnewedge(int u,int v,int w)
{
newedge[newtot].u=u;
newedge[newtot].v=v;
newedge[newtot].w=w;
newedge[newtot].nx=newhead[u];
newhead[u]=newtot++;
}
int set[N];
inline int findset(int x){return x==set[x]?x:set[x]=findset(set[x]);}
inline void kruskal()
{
sort(edge,edge+tot);
int cnt=0;
_rep(i,1,n)set[i]=i;
_for(i,0,tot)
{
int u=edge[i].u;
int v=edge[i].v;
int w=edge[i].w;
int fu=findset(u);
int fv=findset(v);
if(fu!=fv)
{
set[fv]=fu;
addnewedge(u,v,w);
addnewedge(v,u,w);
if(++cnt==n-1)break;
}
}
}
bool vis[N];
int dep[N];
int fa[N][DEP];
int cap[N][DEP];
inline void bfs(int u)
{
queue<int>que;
while(!que.empty())que.pop();
dep[u]=0;
fa[u][0]=u;
que.push(u);
while(!que.empty())
{
int v=que.front();que.pop();
if(vis[v])continue;
vis[v]=1;
_for(i,1,DEP)
{
fa[v][i]=fa[fa[v][i-1]][i-1];
cap[v][i]=min(cap[v][i-1],cap[fa[v][i-1]][i-1]);
}
for(int i=newhead[v];i!=-1;i=newedge[i].nx)
{
int to=newedge[i].v;
if(to==fa[v][0])continue;
cap[to][0]=newedge[i].w;
dep[to]=dep[v]+1;
fa[to][0]=v;
que.push(to);
}
}
}
inline int lca(int u,int v)
{
int minn=INF;
if(dep[u]>dep[v])swap(u,v);
for(int div=dep[v]-dep[u],i=0;div;div>>=1,i++)
if(div&1)minn=min(minn,cap[v][i]),v=fa[v][i];
if(v==u)return minn;
for(int i=DEP-1;i>=0;i--)
{
if(fa[u][i]==fa[v][i])continue;
minn=min(minn,min(cap[v][i],cap[u][i]));
u=fa[u][i];
v=fa[v][i];
}
minn=min(minn,min(cap[u][0],cap[v][0]));
return minn;
}
int main()
{
//fread(Buf,1,BUF,stdin);
//freopen("in.txt","r",stdin);
scanf("%d%d",&n,&m);
int x,y,z;
memset(head,-1,sizeof(head));
memset(newhead,-1,sizeof(newhead));
_rep(i,1,m)
{
scanf("%d%d%d",&x,&y,&z);
addedge(x,y,z);
}
kruskal();
_rep(i,1,n)if(!vis[i])bfs(i);
scanf("%d",&q);
_rep(i,1,q)
{
scanf("%d%d",&x,&y);
int fx=findset(x);
int fy=findset(y);
if(fx!=fy)
{
//writechar('-');
//write(1);
//writeln();
puts("-1");
continue;
}
//write(lca(x,y));
//writeln();
printf("%d\n",lca(x,y));
}
//fwrite(Out,1,ou-Out,stdout);
return 0;
}