/*
Author: baodat
※\(^o^)/※
Current goal: Training for VNOI shirt
*/
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define FOR(i, l, r) for(int i = l; i <= r; i++)
#define FORD(i, l, r) for(int i = l; i >= r; i--)
#define db double
#define ldb long double
#define all_1(x) (x).begin() + 1, (x).end()
#define all(x) (x).begin(), (x).end()
#define ins insert
#define pb push_back
template<typename T>void debug_var(const T& var, const string& name){
cerr << name << ": " << var << "\n";
}
template<typename T>void debug_1d(const T& vt, const string& name){
if(vt.empty()){
cerr << name << " is empty!\n";
return;
}
FOR(i, 0, (int)vt.size() - 1){
cerr << name << "[" << i << "]: " << vt[i] << "\n";
}
}
const ll oo = 2e18;
const int N = 1e5 + 5;
int n, m, k;
struct DSU{
int _n;
vector<int> _par, _rnk;
DSU(int n = 0){
init(n);
}
void init(int n = 0){
_n = n;
_par.assign(_n + 1, 0);
_rnk.assign(_n + 1, 0);
iota(all(_par), 0);
}
int find_u(int u){
return _par[u] == u ? u : _par[u] = find_u(_par[u]);
}
bool unite(int u, int v){
u = find_u(u);
v = find_u(v);
if(u == v) return false;
if(_rnk[u] < _rnk[v]) swap(u, v);
if(_rnk[u] == _rnk[v]) ++_rnk[u];
_par[v] = u;
return true;
}
};
struct Edge{
int v;
ll w;
};
struct Edge2{
int u, v;
ll w;
};
struct Data{
int u, v;
};
struct Data2{
ll mid;
int id;
};
vector<Edge> adj[N];
vector<ll> dijkstra(const vector<int>& ds){
vector<ll>dist(n + 1, oo);
//debug_1d(ds, "ds");
priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<pair<ll, int>>> pq;
for(int it : ds){
dist[it] = 0;
pq.push({0, it});
}
while(!pq.empty()){
auto [dist_u, u] = pq.top();
pq.pop();
if(dist_u != dist[u]) continue;
for(auto[v, w] : adj[u]){
if(dist[v] > dist[u] + w){
dist[v] = dist[u] + w;
pq.push({dist[v], v});
}
}
}
return dist;
}
void solve(){
cin >> n >> m;
vector<Edge2> edges;
FOR(i, 1, m){
int u, v, w;
cin >> u >> v >> w;
edges.pb({u, v, w});
adj[u].pb({v, w});
adj[v].pb({u, w});
}
cin >> k;
vector<int> temp;
FOR(i, 1, k){
int x;
cin >> x;
temp.pb(x);
}
vector<ll> dist = dijkstra(temp);
//FOR(i, 1, n) cout << dist[i] << " ";
vector<int> order(n + 1);
iota(all(order), 0);
sort(all_1(order), [&](int i ,int j){
return dist[i] > dist[j];
});
int q;
cin >> q;
vector<ll> res(q + 1);
vector<Data> queries(q + 1);
FOR(i, 1, q) cin >> queries[i].u >> queries[i].v;
vector<ll> L(q + 1, 0), R(q + 1, oo);
while(true){
bool changed = false;
vector<Data2> ds;
FOR(i, 1, q){
if(L[i] <= R[i]){
ds.pb({(L[i] + R[i]) >> 1, i});
changed = true;
}
}
if(!changed) break;
sort(all(ds), [&](Data2 a, Data2 b){
return a.mid > b.mid;
});
DSU dsu(n);
vector<bool> active(n + 1, false);
int ptr = 0;
for(Data2 it : ds){
ll mid = it.mid;
int i = it.id;
while(ptr < n && dist[order[ptr]] >= mid){
int u = order[ptr];
active[u] = true;
for(auto [v, w] : adj[u]){
if(active[v]) dsu.unite(u, v);
}
++ptr;
}
auto [u, v] = queries[i];
if(dist[u] >= mid && dist[v] >= mid && dsu.find_u(u) == dsu.find_u(v)){
res[i] = mid;
L[i] = mid + 1;
}
else R[i] = mid - 1;
}
}
FOR(i, 1, q) cout << res[i] << "\n";
}
signed main(){
ios_base::sync_with_stdio(0);
cin.tie(0);
int t = 1;
//cin >> t;
while(t--){
solve();
}
return 0;
}