#include<bits/stdc++.h>
#define int long long
#define maxn 100010
#define maxm 200010
using namespace std;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
inline void write(int x){
if(x<0){
putchar('-');
write(-x);
return;
}
if(x>=10)write(x/10);
putchar(x%10+'0');
return;
}
struct node{
int id,dis;
bool operator <(const node &ccf)const{return ccf.dis<dis;}
};
struct EDGE{
int u,v,val,id;bool vis;
}edge[maxm],tree[maxm];
bool cmp(EDGE ccf,EDGE ioi){
return ccf.val<ioi.val;
}
int n,m,cnt=1,ask,a[150][maxn],noip=1,go_up[maxn],ANS[maxn+10];
int fat[maxn],past[maxn],depth[maxn],fa[maxn][150],dis[maxn];
int tdis[maxn];
bool visit[maxn],vist[maxn],VIS[maxn];
int orz=1,fullcombo[maxn];
vector<EDGE>e[maxn],tre[maxn];
void addedge(int from,int to,int val)
{
edge[++cnt].u=from;
edge[cnt].v=to;
edge[cnt].val=val;
edge[cnt].id=cnt;
edge[cnt].vis=false;
e[from].push_back(edge[cnt]);
return;
}
void treeaddedge(int from,int to,int val){
tree[++noip].u=from;
tree[noip].v=to;
tree[noip].id=noip;
tree[noip].vis=false;
tree[noip].val=val;
tre[from].push_back(tree[noip]);
return;
}
int find(int rt){
return (rt==fat[rt])?rt:fat[rt]=find(fat[rt]);
}
void kelusikaer(){
sort(2+edge,1+edge+cnt,cmp);
for(int i=2;i<=2+m*2;++i){
int from=find(edge[i].u);
int to=find(edge[i].v);
if(from!=to){
treeaddedge(edge[i].u,edge[i].v,edge[i].val);
treeaddedge(edge[i].v,edge[i].u,edge[i].val);
edge[i].vis=1;
edge[i^1].vis=1;
fat[from]=to;
}
}
return;
}
void dfs(int rt,int ffa){
depth[rt]=depth[ffa]+1;
for(int i=0;i<=19;++i)
fa[rt][i+1]=fa[fa[rt][i]][i];
for(int i=0;i<tre[rt].size();++i){
int to=tre[rt][i].v;
int val=tre[rt][i].val;
if(to==ffa)continue;
fa[to][0]=rt;tdis[to]=tdis[rt]+val;
dfs(to,rt);
}
return;
}
void dj(int rt){
for(int i=1;i<=n;++i)dis[i]=1e12;
dis[rt]=0;
memset(vist,0,sizeof vist);
priority_queue<node>Q;
while(!Q.empty())Q.pop();
Q.push(node{rt,0});
while(!Q.empty()){
int now=Q.top().id;
int nowdis=dis[now];
Q.pop();
if(!vist[now]){
vist[now]=1;
for(int i=0;i<e[now].size();++i){
int to=e[now][i].v;
int val=e[now][i].val;
if(nowdis+val<dis[to]){
dis[to]=nowdis+val;
if(!vist[to])Q.push(node{to,dis[to]});
}
}
}
}
for(int i=1;i<=n;++i)a[fullcombo[rt]][i]=dis[i];
return;
}
int lca(int x,int y){
if(depth[x]<depth[y])swap(x,y);
for(int i=20;i>=0;i--){
if(depth[fa[x][i]]>=depth[y])x=fa[x][i];
}
if(x==y)return x;
for(int i=20;i>=0;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
signed main()
{
n=read();m=read();
for(int i=1;i<=n;++i)fat[i]=i;
for(int i=1;i<=m;++i){
int from=read();
int to=read();
int value=read();
addedge(from,to,value);
addedge(to,from,value);
}
kelusikaer();
depth[1]=1;tdis[1]=0;
dfs(1,0);
memset(VIS,0,sizeof VIS);
memset(visit,0,sizeof visit);
for(int i=1;i<=m+10;++i){
if(!edge[i].vis){
visit[edge[i].u]=1;
visit[edge[i].v]=1;
}
}
for(int i=1;i<=n;++i){
if(visit[i]&&!VIS[i]){
VIS[i]=1;
fullcombo[i]=++orz;
}
}
for(int i=1;i<=n;++i){if(visit[i])dj(i);}
ask=read();
for(int i=1;i<=ask;++i){
int first=read(),second=read();
int father=lca(first,second);
int res=first;
int ans=tdis[first]+tdis[second]-2*tdis[father];
if(visit[first]){ans=min(ans,a[fullcombo[first]][second]);}
if(visit[second]){ans=min(ans,a[fullcombo[second]][first]);}
ANS[i]=ans;
}
for(int i=1;i<=ask;++i){write(ANS[i]);putchar('\n');}
return 0;
}