#include<stdio.h>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=10001,maxm=50001;
const int INF=0x7fffffff;
struct Node{
int s,t,d;
}e[maxm];
struct Edge{
int e,v;
}tmp;
inline bool cmp(struct Node a,struct Node b){
return a.d>b.d;
}
struct Set{
int root[maxn];
void init(int N){
for(int i=1;i<=N;i++)root[i]=0;
}
int find(int s){
if(root[s]==0)return s;
int e=find(root[s]);
return root[s]=e;
}
void merge(int s,int e){
root[find(s)]=find(e);
}
}R;
struct Truck{
vector <struct Edge> ADJL[maxn];
int up[maxn][20],Min[maxn][20],h[maxn],N,M,Q;
bool f[maxn];
void BuildTree(int v){
f[v]=0;
vector <struct Edge>::iterator it;
for(it=ADJL[v].begin();it!=ADJL[v].end();it++){
if(f[it->e]){
up[it->e][0]=v;
Min[it->e][0]=it->v;
h[it->e]=h[v]+1;
BuildTree(it->e);
}
}
}
void init(){
scanf("%d%d",&N,&M);
for(int i=0;i<M;i++)scanf("%d%d%d",&e[i].s,&e[i].t,&e[i].d);
sort(e,e+M,cmp);
R.init(N);
for(int i=0;i<M;i++)
if(R.find(e[i].s)!=R.find(e[i].t)){
R.merge(e[i].s,e[i].t);
tmp.e=e[i].t;tmp.v=e[i].d;
ADJL[e[i].s].push_back(tmp);
tmp.e=e[i].s;
ADJL[e[i].t].push_back(tmp);
}
memset(f,true,sizeof(f));
for(int i=0;i++<N;)
if(f[i])h[i]=0,BuildTree(i),Min[i][0]=INF,up[i][0]=i;
for(int i=0;i++<19;){
for(int j=0;j++<N;){
up[j][i]=up[up[j][i-1]][i-1];
Min[j][i]=min(Min[j][i-1],Min[up[j][i-1]][i-1]);
}
}
}
int Move(int &v,int H){
int rec=INF;
for(int i=19;i>=0;i--){
if(h[up[v][i]]>=H){
rec=min(rec,Min[v][i]);
v=up[v][i];
}
}
return rec;
}
int solve(int u,int v){
if(R.find(u)!=R.find(v))return -1;
int rec=INF;
if(h[u]!=h[v])rec=h[u]>h[v]?Move(u,h[v]):Move(v,h[u]);
if(u==v)return rec;
for(int i=19;i>=0;i--){
if(up[u][i]!=up[v][i]){
rec=min(rec,min(Min[u][i],Min[v][i]));
u=up[u][i],v=up[v][i];
}
}
rec=min(rec,min(Min[u][0],Min[v][0]));
return rec;
}
void work(){
scanf("%d",&Q);
while(Q--){
int u,v;
scanf("%d%d",&u,&v);
printf("%d\n",solve(u,v));
}
}
}sol;
int main(){
sol.init();
sol.work();
return 0;
}