#include <bits/stdc++.h>
using namespace std;
#define mset(x,val) memset(x,val,sizeof(x))
#define allof(x) x.begin(), x.end()
#define fi first
#define se second
using ll = long long;
using vi = vector<int>;
using vii = vector<vector<int>>;
using vl = vector<long long>;
using vll = vector<vector<long long>>;
using vb = vector<bool>;
using vbb = vector<vector<bool>>;
using mii = map<int,int>;
using umii = unordered_map<int,int>;
using pii = pair<int,int>;
using pll = pair<long long,long long>;
using pli = pair<long long, int>;
using pil = pair<int, long long>;
#define __builtin_popcount __builtin_popcountll
#define BIT(x, i) (((x) >> (i)) & 1)
#define MASK(x) ((1ll << (x)))
#define debug(a, l, r) for (int _i = (l); _i <= (r); ++_i) cout << (a)[_i] << ' '; cout << '\n';
const int MOD = 1e9 + 7;
const int maxn = 1e5 + 5;
int n, m, q, k;
vector <vector<pil>> adj;
vector <vector<pil>> g;
vi sz, par, depth, heavy, head, pos;
vl dist, val;
vi k_rooms;
ll INF = 1e18;
int cur_pos=0;
struct DSU
{
int n;
vi par, sz;
DSU () {}
DSU (int _n)
{
n = _n;
par.resize(n+1);
iota(allof(par), 0);
sz.assign(n+1, 1);
}
int find(int x)
{
if (x == par[x]) return x;
return par[x] = find(par[x]);
}
bool unite(int u, int v)
{
u = find(u);
v = find(v);
if (u == v) return 0;
if (sz[u] < sz[v]) swap(u, v);
par[v] = u;
sz[u] += sz[v];
return 1;
}
};
vector <pair<ll, pii> > edges;
DSU dsu;
void kruskal()
{
dsu = DSU(n);
vector <pair<ll, pii>> new_edges;
for (auto &e : edges)
{
new_edges.push_back({min(dist[e.se.fi], dist[e.se.se]), {e.se.fi, e.se.se}});
}
sort(allof(new_edges), greater<>());
for (auto &e : new_edges)
{
int u = e.se.fi;
int v = e.se.se;
ll w = e.fi;
if(dsu.unite(u, v))
{
adj[u].push_back({v, w});
adj[v].push_back({u, w});
}
}
}
void dijkstra(int n)
{
dist.assign(n+1, INF);
priority_queue<pli, vector<pli>, greater<pli>> pq;
for (int x : k_rooms)
{
pq.push({0, x});
dist[x]=0;
}
while(!pq.empty())
{
int u = pq.top().se;
ll d = pq.top().fi;
pq.pop();
if (d != dist[u]) continue;
for (auto &E : g[u])
{
int v = E.fi;
ll w = E.se;
if (dist[v] > dist[u] + w)
{
dist[v] = dist[u] + w;
pq.push({dist[v], v});
}
}
}
}
struct SegmentTree_Min
{
vl vec;
vl st;
SegmentTree_Min(){}
SegmentTree_Min(int n)
{
vec.resize(n+1);
st.resize(4*n+5);
}
void build(int id, int l, int r)
{
if (l > r) return;
if (l==r)
{
st[id] = vec[l];
return;
}
int mid = (l + r ) >> 1;
build(id<<1, l, mid);
build(id<<1|1, mid+1, r);
st[id] = min(st[id<<1], st[id<<1|1]);
}
ll query(int id, int l, int r, int ql, int qr)
{
if (r < ql || l > qr) return LLONG_MAX;
if (ql <= l && r <= qr) return st[id];
int mid = (l + r) >> 1;
return min(query(id<<1, l, mid, ql, qr), query(id<<1|1, mid+1, r, ql, qr));
}
};
int dfs(int u, int p)
{
depth[u] = depth[p] + 1;
par[u] = p;
sz[u] =1;
int mx_cnt = 0;
for (auto &e: adj[u])
{
int v = e.fi;
ll w = e.se;
if (v == p) continue;
val[v] = w;
int s = dfs(v, u);
sz[u] += s;
if (s > mx_cnt)
{
mx_cnt = s;
heavy[u]=v;
}
}
return sz[u];
}
SegmentTree_Min ST;
void decompose(int u, int h)
{
head[u] = h;
pos[u] = ++cur_pos;
ST.vec[cur_pos] = val[u];
if (heavy[u]) decompose(heavy[u], h);
for (auto &e : adj[u])
{
int v = e.fi;
if (v == par[u] || v == heavy[u]) continue;
decompose(v, v);
}
}
ll query(int u, int v)
{
ll res = LLONG_MAX;
while(head[u] != head[v])
{
if (depth[head[u]] < depth[head[v]]) swap(u, v);
res = min(res, ST.query(1, 1, n, pos[head[u]] +1, pos[u]));
u = par[head[u]];
}
if (depth[u] > depth[v]) swap(u, v);
return min(res, ST.query(1, 1, n, pos[u] + 1, pos[v]));
}
void Input()
{
cin >> n >> m;
adj.resize(n+1);
g.resize(n+1);
sz.resize(n+1), par.resize(n+1), depth.resize(n+1), heavy.resize(n+1, 0), head.resize(n+1), pos.resize(n+1);
val.resize(n+1);
for (int i=1 ;i<=m; ++i)
{
int u, v;
ll w;
cin>>u>>v>>w;
edges.push_back({w, {u, v}});
g[u].push_back({v, w});
g[v].push_back({u, w});
}
cin>>k;
vb is_k(n+1,0);
for (int i=1; i<=k; ++i)
{
int x;
cin>>x;
k_rooms.push_back(x);
is_k[x]=1;
}
dijkstra(n);
kruskal();
depth[0] = -1;
dfs(1, 0);
ST = SegmentTree_Min(n);
decompose(1, 1);
ST.build(1, 1, n);
// debug(ST.vec, 1, n);
cin>>q;
while(q--)
{
int u, v;
cin>>u>>v;
if (is_k[u] || is_k[v]) cout<<0<<'\n';
else cout<<query(u, v)<<'\n';
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
Input();
return 0;
}