#include<cstdio>
#include<vector>
#include<utility>
#include<queue>
#include<algorithm>

using namespace std;

typedef pair<int,int> P;

class UnionFind{
	int par[100100];
	int rank[100100];
	public:
	void init(int N)
	{
		for(int i=0;i<N;i++)
		{
			par[i]=i;
			rank[i]=0;
		}
	}
	int find(int x)
	{
		if(par[x]==x) return x;
		return par[x]=find(par[x]);
	}
	void unite(int x,int y)
	{
		x=find(x),y=find(y);
		if(rank[x]<rank[y])
		{
			par[x]=y;
			return;
		}
		par[y]=x;
		if(rank[x]==rank[y]) rank[y]++;
	}
	bool same(int x,int y)
	{
		return find(x)==find(y);
	}
};

struct edge{
	int u,v,cost;
	edge(int a,int b,int c):u(a),v(b),cost(c){}
	edge(int a,int c):u(a),v(a),cost(c){}
	edge(){}
};

vector<edge> G[100100];//initial road
vector<int> Gt[100100];//far node tree

vector<edge> es;//for kruskal

int par[20][100100];
int dis[20][100100];

int depth[100100];

void dfs(int p,int v,int dep)
{
	depth[v]=dep;
	par[1][v]=p;
	//vs.push_back(v);
	//bool flg=false;
	for(int i=0;i<Gt[v].size();i++)
	{
		if(Gt[v][i]==p) continue;
		//flg=true;
		dfs(v,Gt[v][i],dep+1);
		//vs.push_back(v);
	}
}

UnionFind uf;//for kruskal

bool cmp(const edge &e1,const edge &e2)
{
	return e1.cost<e2.cost;
}

int main()
{
	int N,M,K,Q;
	scanf("%d%d%d%d",&N,&M,&K,&Q);
	for(int i=0;i<M;i++)
	{
		int a,b,l;
		scanf("%d%d%d",&a,&b,&l);
		a--;b--;
		es.push_back(edge(a,b,-1));
		G[a].push_back(edge(b,l));
		G[b].push_back(edge(a,l));
	}
	for(int i=0;i<N;i++)
	{
		for(int j=0;j<20;j++)
		{
			dis[j][i]=1<<30;
		}
	}
	priority_queue<P,vector<P>,greater<P> > que;
	for(int i=0;i<K;i++)
	{
		int u;
		scanf("%d",&u);
		u--;
		dis[0][u]=0;
		que.push(P(0,u));
	}
	while(!que.empty())
	{
		P p=que.top();
		que.pop();
		int v=p.second;
		int t=p.first;
		for(int i=0;i<G[v].size();i++)
		{
			int nv=G[v][i].u;
			int nt=G[v][i].cost+t;
			if(dis[0][nv]<=nt) continue;
			dis[0][nv]=nt;
			que.push(P(nt,nv));
		}
	}
	for(int i=0;i<M;i++)
	{
		es[i].cost=min(dis[0][es[i].u],dis[0][es[i].v]);
	}
	sort(es.begin(),es.end(),cmp);
	reverse(es.begin(),es.end());
	uf.init(N);
	for(int i=0;i<M;i++)
	{
		int u=es[i].u;
		int v=es[i].v;
		if(!uf.same(u,v))
		{
			Gt[u].push_back(v);
			Gt[v].push_back(u);
			uf.unite(u,v);
		}
	}
	dfs(-1,0,0);
	for(int i=0;i<N;i++)
	{
		par[0][i]=i;
	}
	for(int i=1;i<19;i++)
	{
		for(int j=0;j<N;j++)
		{
			if(par[i][j]==-1) par[i+1][j]=-1;
			else par[i+1][j]=par[i][par[i][j]];
		}
	}
	for(int i=0;i<19;i++)
	{
		for(int j=0;j<N;j++)
		{
			if(par[i][j]==-1) dis[i+1][j]=dis[i][j];
			if(i!=0) dis[i+1][j]=min(dis[i][j],dis[i][par[i][j]]);
			else dis[i+1][j]=min(dis[i][j],dis[i][par[i+1][j]]);
		}
	}
	for(int i=0;i<N;i++)
	{
//		printf("%d:",i);
		for(int j=0;j<4;j++)
		{
	//		printf("%d ",par[j][i]);
		}
	//	printf("\n");
	}
	for(int i=0;i<N;i++)
	{
	//	printf("%d:",i);
		for(int j=0;j<4;j++)
		{
	//		printf("%d ",dis[j][i]);
		}
	//	printf("\n");
	}

	for(int i=0;i<Q;i++)
	{
		int A,B;
		scanf("%d%d",&A,&B);
		A--;B--;
		int ans=1<<30;
		int a=depth[A],b=depth[B];
		if(a<b) swap(A,B);
		for(int j=0;j<19;j++)
		{
			if(((depth[A]-depth[B])>>j)%2==1)
			{
				ans=min(ans,dis[j+1][A]);
				A=par[j+1][A];
			}
		}
		//printf("%d %d %d\n",A,B,ans);
		if(A==B)
		{
			printf("%d\n",ans);
			continue;
		}
		for(int j=19;j>=0;j--)
		{
			if(par[j][A]!=par[j][B])
			{
				ans=min(ans,dis[j][A]);
				ans=min(ans,dis[j][B]);
				A=par[j][A];
				B=par[j][B];
			}
		}
		ans=min(ans,dis[1][A]);
		printf("%d\n",ans);
	}
	return 0;
}

Measured memory_bytes: 30000