#include<bits/stdc++.h>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<string.h>
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
using namespace std;
const ll INF=0x7f7f7f7f7f,inf=0x3f3f3f3f3f;
namespace Yorihime_Nao{
template<class T> T MAX(T x,T y){
return x>y?x:y;
}
template<class T,class ... Arg> T MAX(T x,T y,Arg ... arg){
return MAX(x>y?x:y,arg...);
}
template<class T> T MIN(T x,T y){
return x<y?x:y;
}
template<class T,class ... Arg> T MIN(T x,T y,Arg ... arg){
return MIN(x<y?x:y,arg...);
}
template<class T> T lowbit(T x){
return x&-x;
}
template<class T> void SWAP(T &x,T &y){
x^=y^=x^=y;
return;
}
}
using namespace Yorihime_Nao;
const ll MAXN=1e4+5,MAXM=5e4+5;
ll n,m,x,y,z,q;
struct edge{
ll u,v,w,nxt;
bool operator < (const edge &oth)const{
return w>oth.w;
}
};
edge e[MAXM],tree[MAXN<<1];
ll edge_num,head[MAXN],tree_cnt,tree_head[MAXN];
void add_edge(ll From,ll To,ll Len){
edge_num++;
e[edge_num].u=From;
e[edge_num].v=To;
e[edge_num].w=Len;
e[edge_num].nxt=head[From];
head[From]=edge_num;
return;
}
void add_tree(ll From,ll To,ll Len){
tree_cnt++;
tree[tree_cnt].u=From;
tree[tree_cnt].v=To;
tree[tree_cnt].w=Len;
tree[tree_cnt].nxt=tree_head[From];
tree_head[From]=tree_cnt;
return;
}
ll _fa[MAXN];
ll Find(ll now){
return _fa[now]==now?now:_fa[now]=Find(_fa[now]);
}
void kruskal(){
for(int i=1;i<=n;i++)_fa[i]=i;
sort(e+1,e+1+edge_num);
ll cnt=0;
for(int i=1;i<=edge_num;i++){
ll f_u=Find(e[i].u),f_v=Find(e[i].v);
if(f_u==f_v)continue;
cnt++;
_fa[f_u]=f_v;
add_tree(e[i].u,e[i].v,e[i].w);
add_tree(e[i].v,e[i].u,e[i].w);
if(cnt==n-1)break;
}
return;
}
ll deep[MAXN],fa[MAXN][25],sw[MAXN][25];
bool vis[MAXN];
void pre(ll now,ll father){
if(vis[now])return;
vis[now]=1;
deep[now]=deep[father]+1;
for(int i=1;i<=20;i++)fa[now][i]=fa[fa[now][i-1]][i-1];
for(int i=1;i<=20;i++)sw[now][i]=MIN(sw[now][i-1],sw[fa[now][i-1]][i-1]);
for(int i=tree_head[now];i;i=tree[i].nxt){
if(tree[i].v==father||vis[tree[i].v])continue;
sw[tree[i].v][0]=tree[i].w;
fa[tree[i].v][0]=now;
pre(tree[i].v,now);
}
}
ll solve(ll p1,ll p2){
if(deep[p1]<deep[p2])SWAP(p1,p2);
ll ans=INF;
for(int i=20;i>=0;i--)if(deep[fa[p1][i]]>=deep[p2])ans=MIN(ans,sw[p1][i]),p1=fa[p1][i];
if(p1==p2)return ans;
for(int i=20;i>=0;i--){
if(fa[p1][i]!=fa[p2][i]){
ans=MIN(ans,sw[p1][i],sw[p2][i]);
p1=fa[p1][i];
p2=fa[p2][i];
}
}
return MIN(ans,sw[p1][0],sw[p2][0]);
}
int main(){
scanf("%lld%lld",&n,&m);
for(int i=1;i<=m;i++){
scanf("%lld%lld%lld",&x,&y,&z);
add_edge(x,y,z);
add_edge(y,x,z);
}
kruskal();
for(int i=1;i<=n;i++)if(!vis[i])pre(i,0);
scanf("%lld",&q);
for(int i=1;i<=q;i++){
scanf("%lld%lld",&x,&y);
if(Find(x)!=Find(y)){
printf("-1\n");
continue;
}
printf("%lld\n",solve(x,y));
}
return 0;
}