import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class F2 {

	static int N,M,K,Q;
	static ArrayList<Edge> adj[];
	//Node to a query
	static HashMap<Integer, Integer> qs[];
	static long answers[];
	static int iAm[];
	static HashSet<Integer> ksInHere[];
	static final boolean debug = false;
	static long INF = 1_000_000_000_000_000_0L;
	public static void main(String args[]) {
		FS in = new FS();
		PrintWriter out = new PrintWriter(System.out);
		N = in.nextInt();
		M = in.nextInt();
		K = in.nextInt();
		Q = in.nextInt();
		adj = new ArrayList[N];
		for(int i = 0; i < N; i++) adj[i] = new ArrayList<Edge>();
		for(int i = 0; i < M; i++) {
			int a = in.nextInt()-1;
			int b = in.nextInt()-1;
			long c = in.nextLong();
			adj[a].add(new Edge(b,c));
			adj[b].add(new Edge(a,c));
		}
		
		qs = new HashMap[N];
		for(int i = 0; i < N; i++) qs[i] = new HashMap<Integer, Integer>();
		iAm = new int[Q];
		Arrays.fill(iAm, -1);
		for(int i = 0; i < Q; i++) {
			int a = in.nextInt()-1;
			int b = in.nextInt()-1;
			if(qs[a].containsKey(b)) {
				iAm[i] = qs[a].get(b);
			}
			else {
				qs[a].put(b, i);
				qs[b].put(a, i);
			}
		}
		
		ksInHere = new HashSet[N];
		for(int i = 0; i < N; i++) {
			ksInHere[i] = new HashSet<Integer>();
			if(i < K) ksInHere[i].add(i);
		}
		answers = new long[Q];
		Arrays.fill(answers, -1);
		dji();
		for(int i = 0; i < Q; i++) {
			if(iAm[i] != -1) answers[i] = answers[iAm[i]];
		}
		for(long ll : answers) out.println(ll);
		out.close();
	}
	
	static void dji() {
		PriorityQueue<State> pq = new PriorityQueue<State>();
		DSU dsu = new DSU(N);
		for(int i = 0; i < K; i++) {
			for(Edge e : adj[i]) {
				pq.add(new State(i, e.to, e.c, e.c));
			}
		}
		long caps[] = new long[N];
		Arrays.fill(caps, INF);
		for(int i = 0; i < K; i++) caps[i] = 0;
		while(!pq.isEmpty()) {
			State s = pq.poll();
			caps[s.to] = Math.min(caps[s.to], s.capNeeded);
			if(debug) {
				System.out.println("S: "+s);
				System.out.println("  dsu= "+dsu.find(s.from)+"   "+dsu.find(s.to));
			}
			int fP = dsu.find(s.from);
			int tP = dsu.find(s.to);
			if(fP != tP) {
				//we union these and answer the queries
				union(fP, tP, dsu, caps[s.from], caps[s.to], s.edge);
				
				int fromP = dsu.find(s.to);
				for(Edge e : adj[s.to]) {
					//go to the next guy
					int toP = dsu.find(e.to);
					if(fromP == toP) continue;
					// add this guy to the queue
					pq.add(new State(s.to, e.to, s.capNeeded + e.c, e.c));
				}	
			}
			//We only check new edges if we are dsu'ing something new

		}
		
		HashSet<Integer> dd = new HashSet<Integer>();
		for(int i = 0; i < N; i++) dd.add(dsu.find(i));
		if(dd.size() != 1) throw null;
		
	}
	
	static void union(int a, int b, DSU dsu, long c1, long c2, long edge) {
		//small to big
//		if(ksInHere[a].size() < ksInHere[b].size()) {
//			for(int ii : ksInHere[a]) {
//				
//			}
//		}
		long res = -1;
		if(c1 == INF) res = c2+edge;
		else if(c2 == INF) res = c1+edge;
		else res = c1+c2+edge;
		
		
		for(int ii : ksInHere[a]) {
			for(int q : qs[ii].keySet()) {
				if(ksInHere[b].contains(q)) {
					answers[qs[ii].get(b)] = res;
				}
			}
		}
		
		
		
		dsu.union(a,b);
		ksInHere[dsu.find(a)].addAll(ksInHere[a]);
		ksInHere[dsu.find(b)].addAll(ksInHere[b]);
	}
	
	static class Edge{
		int to;
		long c;
		public Edge(int tt, long cc) {
			to=tt;
			c=cc;
		}
	}
	
	static class State implements Comparable<State>{
		int from, to;
		long capNeeded;
		long edge;
		public State(int ff, int tt, long cc, long ee) {
			from=ff;
			to=tt;
			capNeeded = cc;
			edge = ee;
		}
		@Override
		public int compareTo(State o) {
			return Long.compare(capNeeded, o.capNeeded);
		}
		@Override
		public String toString() {
			return "["+from+" -> "+to+" need="+capNeeded+"]";
		}
	}
	
	static class DSU {
		int[] s;
		
		public DSU(int n) {
			Arrays.fill(s = new int[n], -1);
		}
		
		public int find(int i) {
			return s[i] < 0 ? i : (s[i] = find(s[i]));
		}
		
		public boolean union(int a, int b) {
			if ((a = find(a)) == (b = find(b))) return false;
			if(s[a] == s[b]) s[a]--;
			if(s[a] <= s[b]) s[b] = a; else s[a] = b;
			return true;
		}
	}

	
	
	
	static class FS{
		BufferedReader br;
		StringTokenizer st;
		public FS(String s) throws Exception {
			try{ br = new BufferedReader(new FileReader(s)); }
			catch(Exception e) { throw new Exception(); }
		}
		public FS(){
			br = new BufferedReader(new InputStreamReader(System.in));
		}
		String nextToken()	{
			while(st == null ||!st.hasMoreElements()){
				try { st = new StringTokenizer(br.readLine());}
				catch(IOException e) { e.printStackTrace(); }			
			}
			return st.nextToken();
		}
		int nextInt() {
			return Integer.parseInt(nextToken());
		}
		long nextLong() {
			return Long.parseLong(nextToken());
		}
		double nextDouble() {
			return Double.parseDouble(nextToken());
		}
		String next() {
			return nextToken();
		}

	}
}
