#include <iostream>
#include <vector>
#include <queue>
#include <utility>
#include <tuple>
#include <set>
#include <algorithm>

using namespace std;

using Pii = pair<int, int>;

constexpr int INF = 1 << 28;

class UnionFind {
    public:
    int n;
    vector<int> par, rank;

    UnionFind(int n): n(n) {
        for(int i=0;i<n;++i) {
            par.push_back(i);
            rank.push_back(0);
        }
    }

    int find(int x) {
        return ((par[x] == x) ? x : par[x] = find(par[x]));
    }

    void unite(int x, int y) {
        x = find(x);
        y = find(y);

        if(x == y) return;

        if(rank[x] < rank[y]){
            par[x] = y;
        }else{
            par[y] = x;
            if(rank[x] == rank[y]) rank[x]++;
        }
        return;
    }

    bool is_same(int x, int y) {
        return find(x) == find(y);
    }
};

int main() {
    int n, m, k, q, a, b, l;
    cin >> n >> m >> k >> q;
    vector<Pii> graph[n];
    vector<tuple<int, int, int>> edges;
    for(int i=0;i<m;++i) {
        cin >> a >> b >> l;
        --a; --b;
        graph[a].emplace_back(b, l);
        graph[b].emplace_back(a, l);
        edges.emplace_back(l, a, b);
    }

    vector<int> dist(n, INF);
    for(int i=0;i<k;++i) {
        cin >> a;
        --a;
        dist[a] = 0;
    }

    priority_queue<Pii, vector<Pii>, greater<Pii>> que;
    for(int i=0;i<n;++i) if(dist[i] == 0) que.emplace(0, i);
    while(!que.empty()) {
        Pii p = que.top(); que.pop();
        if(dist[p.second] < p.first) continue;
        for(Pii nxt: graph[p.second]) {
            if(p.first + nxt.second < dist[nxt.first]) {
                dist[nxt.first] = p.first + nxt.second;
                que.emplace(p.first + nxt.second, nxt.first);
            }
        }
    }
    for(int i=0;i<m;++i) {
        get<0>(edges[i]) = min(dist[get<1>(edges[i])], dist[get<2>(edges[i])]);
    }
    sort(edges.rbegin(), edges.rend());

    vector<Pii> query(q);
    for(int i=0;i<q;++i) {
        cin >> query[i].first >> query[i].second;
        --query[i].first;
        --query[i].second;
    }

    bool finished = true;
    vector<int> ng(q, INF), ok(q, 0);   // 最小値を ok[i] 以下にならできる，ng[i] 以上にはできない 
    vector<int> mid(q);
    set<Pii> st;
    for(int i=0;i<q;++i) {
        if(dist[query[i].first] == 0 || dist[query[i].second] == 0) {
            ok[i] = 0;
            ng[i] = 1;
            continue;
        }
        if(ng[i] - ok[i] <= 1) continue;
        finished = false;
        mid[i] = (ng[i] + ok[i]) / 2;
        st.emplace(-mid[i], i);
    }
    while(!finished) {
        UnionFind uf = UnionFind(n);
        {
            int mi, i, ei = 0;
            for(Pii p: st) {
                tie(mi, i) = p;
                mi *= -1;
                while(ei < m && get<0>(edges[ei]) >= mi) {
                    // cerr << get<0>(edges[ei]) << " " << get<1>(edges[ei]) << " " << get<2>(edges[ei]) << endl;
                    uf.unite(get<1>(edges[ei]), get<2>(edges[ei]));
                    ++ei;
                }
                if(uf.is_same(query[i].first, query[i].second)) {
                    ok[i] = mi;
                } else {
                    ng[i] = mi;
                }
            }
        }
 
        finished = true;
        st.clear();
        for(int i=0;i<q;++i) {
            if(ng[i] - ok[i] <= 1) continue;
            finished = false;
            mid[i] = (ng[i] + ok[i]) / 2;
            st.emplace(-mid[i], i);
        }
    }

    for(int i=0;i<q;++i) {
        cout << ok[i] << endl;
    }
}


Measured memory_bytes: 22636