#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int>P;

struct UF{
    int N;
    vector<int>par,sz;

    void init(int n){
        N=n;
        par.resize(N);
        sz.resize(N,1);
        for(int i=0;i<N;i++)par[i]=i;
    }

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

    void unite(int x,int y){
        x=find(x);y=find(y);
        if(x==y)return;
        if(sz[x]<sz[y])swap(x,y);
        par[y]=x;
        sz[x]+=sz[y];
    }

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

};

struct edge{
    int to,cost;
    edge(int a,int b):to(a),cost(b){}
};

struct edge2{
    int u,v,cost;
    edge2(int a,int b,int c):u(a),v(b),cost(c){}
    bool operator<(const edge2 &e)const{
        return cost<e.cost;
    }
};

const int INF=1001001001;

int N,M,K,Q;

vector<edge>G[100000];
vector<edge>Tree[100000];
vector<int>fes;
int dist[100000];
int par[20][100000],mincost[20][100000];
int depth[100000];

void dijkstra(){
    priority_queue<P,vector<P>,greater<P> >Q;
    fill_n(dist,100000,INF);
    for(int i=0;i<K;i++){
        dist[fes[i]]=0;
        Q.push(P(0,fes[i]));
    }

    while(Q.size()){
        P p=Q.top();Q.pop();
        if(dist[p.second]<p.first)continue;

        for(int i=0;i<G[p.second].size();i++){
            edge &e=G[p.second][i];
            if(dist[e.to]<=p.first+e.cost)continue;
            dist[e.to]=p.first+e.cost;
            Q.push(P(dist[e.to],e.to));
        }
    }
}

void make_tree(){
    vector<edge2>es;
    for(int i=0;i<N;i++){
        for(int j=0;j<G[i].size();j++){
            edge &e=G[i][j];
            es.push_back(edge2(i,e.to,min(dist[i],dist[e.to])));
        }
    }

    sort(es.begin(),es.end());
    reverse(es.begin(),es.end());
    UF uf;uf.init(N);

    for(int i=0;i<es.size();i++){
        edge2 &e=es[i];
        if(uf.same(e.u,e.v))continue;
        uf.unite(e.u,e.v);
        Tree[e.u].push_back(edge(e.v,e.cost));
        Tree[e.v].push_back(edge(e.u,e.cost));
    }
}

void dfs(int v,int p,int d){
    depth[v]=d;
    par[0][v]=p;
    for(int i=0;i<Tree[v].size();i++){
        edge &e=Tree[v][i];
        if(e.to==p){
            mincost[0][v]=e.cost;
        }
        else{
            dfs(e.to,v,d+1);
        }
    }
}

int calc(int u,int v){
    if(depth[u]>depth[v])swap(u,v);

    int ret=INF;
    for(int i=0;i<20;i++){
        if((depth[v]-depth[u])>>i&1){
            ret=min(ret,mincost[i][v]);
            v=par[i][v];
        }
    }

    if(u==v)return ret;

    for(int i=19;i>=0;i--){
        if(par[i][u]==par[i][v])continue;
        ret=min(ret,min(mincost[i][u],mincost[i][v]));
        u=par[i][u];
        v=par[i][v];
    }

    return min(ret,min(mincost[0][u],mincost[0][v]));
}

int main(){
    cin>>N>>M>>K>>Q;

    for(int i=0;i<M;i++){
        int a,b,c;
        cin>>a>>b>>c;
        a--;b--;
        G[a].push_back(edge(b,c));
        G[b].push_back(edge(a,c));
    }

    fes.resize(K);
    for(int i=0;i<K;i++){
        cin>>fes[i];fes[i]--;
    }

    dijkstra();
    make_tree();

    fill_n(*par,20*100000,-1);
    fill_n(*mincost,20*100000,INF);
    dfs(0,-1,0);

    for(int i=1;i<20;i++){
        for(int j=0;j<N;j++){
            if(par[i-1][j]==-1)continue;
            par[i][j]=par[i-1][par[i-1][j]];
            mincost[i][j]=min(mincost[i-1][j],mincost[i-1][par[i-1][j]]);
        }
    }


    for(int i=0;i<Q;i++){
        int u,v;
        cin>>u>>v;
        u--;v--;
        cout<<calc(u,v)<<endl;
    }
    return 0;
}

Measured memory_bytes: 32380