#include <bits/stdc++.h>
using namespace std;
#define _USE_MATH_DEFINES

#include <ext/rope>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_cxx;
using namespace __gnu_pbds;
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
typedef complex<ld> pt;

const char nl = '\n';
const ll INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
const ll MOD = 1e9+7;
const ld EPS = 1e-13;
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());

struct Edge {
	int i; ll d;
	bool operator < (const Edge& o) const {
		return d > o.d;
	}
};

struct MSTE {
	int a, b; ll c;
	bool operator < (const MSTE& o) const {
		return c < o.c;
	}
};

const int N = 1e5+1;
ll dist[N];
vector<Edge> graph[N];
vector<int> adj[N];

int dsu[N];
int find(int i) {
	if(dsu[i]==0) return i;
	return dsu[i] = find(dsu[i]);
}
int link(int i, int j) {
	if(find(i)==find(j)) return 0;
	dsu[find(i)] = find(j);
	return 1;
}

struct SegTree { int n; ll *segt; // EXAMPLE
  SegTree(int len) { n = 1<<(32-__builtin_clz(len));
    segt = new ll[2*n]; fill(segt, segt+2*n, 0);
	}
  void update(int x, ll v) {
		segt[x+=n] = v;
		for(x/=2; x>0; x/=2) {
			segt[x] = max(segt[2*x], segt[2*x+1]);
		}
	}
	ll query(int l, int r) {
		ll res = 0;
		for(l+=n,r+=n+1; l<r; l/=2,r/=2) {
			if(l&1) res = max(res, segt[l++]);
			if(r&1) res = max(res, segt[--r]);
		}
		return res;
	}
};

namespace HLD { SegTree* segt[N];
  int d[N], par[N], sub[N], sz[N], root[N], ch[N], pos[N]; int dn, cn;
  int dfs(int u, int p) { d[u] = d[par[u]=p]+1; sub[u] = 1;
    for (int x:adj[u]) if (x!=p) sub[u] += dfs(x,u); return sub[u]; }
  void hld(int u, int p) { if (dn == cn) { root[cn]=u; sz[cn++]=0; }
    pos[u] = sz[ch[u]=dn]++; int b=-1, c=-1;
    for (int x:adj[u]) if (x!=p && sub[x]>b) b=sub[c=x]; if (c!=-1) hld(c,u);
    for (int y:adj[u]) if (y!=p && y!=c) { dn++; hld(y,u); } }
  void build(int r) { d[0] = dn = cn = 0; dfs(r,0); hld(r,0);
    for (int i=0; i<cn; i++) segt[i] = new SegTree(sz[i]); }
  // Returns LCA of path ab, MODIFY for insert_node, query_path, query_node
  ll query_path(int a, int b) {
		ll res = 0;
    while (ch[a] != ch[b]) { if (d[root[ch[a]]] < d[root[ch[b]]]) swap(a,b);
      res = max(res, segt[ch[a]]->query(0, pos[a])); a = par[root[ch[a]]]; }
    if (pos[a] != pos[b]) { if (d[a] < d[b]) swap(a,b);
      res = max(res, segt[ch[a]]->query(pos[b]+1, pos[a])); }
		return res;
	}
	void insert_node(int a, ll v) {
		segt[ch[a]]->update(pos[a], v);
	}
}

int main() {
	ios::sync_with_stdio(0); cin.tie(0);
	cout << fixed << setprecision(10);

	int n,m,k,q;
	cin>>n>>m>>k>>q;
	vector<MSTE> edges;
	for(int i=0;i<m;i++) {
		int a,b,c;
		cin>>a>>b>>c;
		graph[a].push_back({b,c});
		graph[b].push_back({a,c});
		edges.push_back({a,b,c});
	}

	priority_queue<Edge> dijk;
	for(int i=1;i<=k;i++) {
		dijk.push({i,0});
	}
	for(int i=k+1;i<=n;i++) {
		dist[i] = INFLL;
	}
	while(!dijk.empty()) {
		Edge cur = dijk.top();
		dijk.pop();
		if(cur.d > dist[cur.i]) continue;
		for(const Edge& e:graph[cur.i]) {
			if(e.d + cur.d < dist[e.i]) {
				dist[e.i] = e.d + cur.d;
				dijk.push({e.i, dist[e.i]});
			}
		}
	}

	for(MSTE& e : edges) {
		e.c += dist[e.a] + dist[e.b];
	}
	sort(edges.begin(), edges.end());

	vector<MSTE> hlde;
	for(const MSTE& e : edges) {
		if(link(e.a, e.b)) {
			adj[e.a].push_back(e.b);
			adj[e.b].push_back(e.a);
			hlde.push_back(e);
		}
	}

	HLD::build(1);
	for(const MSTE& e : hlde) {
		if(HLD::par[e.a] == e.b) {
			HLD::insert_node(e.a, e.c);
		} else {
			assert(HLD::par[e.b] == e.a);
			HLD::insert_node(e.b, e.c);
		}
	}

	for(int i=0;i<q;i++) {
		int a,b;
		cin>>a>>b;
		cout<<HLD::query_path(a, b)<<nl;
	}

	return 0;
}


#include <bits/stdc++.h>

#define x first
#define y second

using namespace std;
using INT = long long;
using pii = pair<INT, INT>;

const int NN=600030, M = 21;

int dep[NN], p[NN][M], rt[NN], fa[NN];
vector<INT> tadj[NN];
vector<pii> adj[NN];
INT dst[NN], val[NN];

void dfs(int u, int pa=0) {
	p[u][0]=pa; dep[u]=dep[pa]+1;
	for (int i=1; i<M; i++) p[u][i]=p[p[u][i-1]][i-1];
	for (int v : tadj[u]) dfs(v, u);
}

int k_th(int u, int k) {
	while (k) {
		u=p[u][__builtin_ctz(k)];
		k^=k&-k;
	}
	return u;
}

int lca(int u, int v) {
	if (dep[u]>dep[v]) swap(u, v);
	v=k_th(v, dep[v]-dep[u]);
	if (u==v) return u;
	for (int t=M; t--; ) {
		if (p[u][t]!=p[v][t]) u=p[u][t], v=p[u][t];
	}
	return p[u][0];
}

int find(int u) {return rt[u]==u?u:rt[u]=find(rt[u]);}

int main(){
#ifndef ONLINE_JUDGE
	freopen("in.in", "r", stdin);
	freopen("out.out", "w", stdout);
#endif

	int n, m, K, Q, u, v, w;
	cin>>n>>m>>K>>Q;
	for (int i=0; i<m; i++) {
		scanf("%d%d%d", &u, &v, &w);
		adj[u].emplace_back(v, w);
		adj[v].emplace_back(u, w);
	}

	for (int i=K+1; i<=n; i++) dst[i]=1LL<<60;
	set<pair<INT, INT>> st;
	for (int i=1; i<=n; i++) st.insert({dst[i], i});
	for (int i=1; i<=K; i++) fa[i]=i;
	for (int i=1; i<=n; i++) {
		int u=st.begin()->y; st.erase(st.begin());
		for (auto t : adj[u]) {
			if (dst[t.x]>dst[u]+t.y) {
				st.erase({dst[t.x], t.x});
				fa[t.x]=fa[u];
				st.insert({dst[t.x]=dst[u]+t.y, t.x});
			}
		}
	}

	vector<pair<INT, pii>> edge;
	for (int i=1; i<=n; i++) {
		for (auto t : adj[i]) if (i>t.x) {
			int u=fa[i], v=fa[t.x];
			if (u==v) continue;
			edge.emplace_back(dst[i]+dst[t.x]+t.y, pii(u, v));
		}
	}
	sort(edge.begin(), edge.end());

	int N = K;
	for (int i=1; i<=K; i++) rt[i]=i;
	for (auto t : edge) {
		int u=find(t.y.x), v=find(t.y.y);
		if (u==v) continue;
		++N;
		tadj[N].push_back(u);
		tadj[N].push_back(v);
		rt[u]=rt[v]=rt[N]=N; val[N]=t.x;
	}
	dfs(N);
	while (Q--) {
		scanf("%d%d", &u, &v);
		printf("%I64d\n", val[lca(u, v)]);
	}

	return 0;
}


#include<bits/stdc++.h>

#define pb push_back
#define x first
#define y second
using namespace std;
typedef long long INT;
typedef pair<INT, int> pii;
using ppi = pair<pii, INT>;

typedef vector<int> VI;
int power(int a, int b, int m, int ans=1) {
	for(; b; b>>=1, a=1LL*a*a%m) if(b&1) ans=1LL*ans*a%m;
	return ans;
}
const int NN = 600011;
vector<pii> adj[NN];
set<pii> s;
int n, m, k, q;
INT dst[NN];
const INT inf = 1e18;
int fa[NN];
INT val[NN];
VI tmp[NN];
int root[NN];
int p[NN][22], deep[NN];

struct LCA {
	void dfs(int u, int fa=0){
		p[u][0]=fa;
		deep[u]=deep[fa]+1;
		for(int i=1; i<21; i++) p[u][i]=p[p[u][i-1]][i-1];
		for(int v :tmp[u]) {
			if(v==fa) continue;
			dfs(v, u);
		}
	}
	int k_th(int u, int k){
		for(; k; ) u = p[u][__builtin_ctz(k&-k)], k-=k&-k;
		return u;
	}
	int lca(int a, int b){
		if(deep[a]>deep[b]) swap(a, b);
		b=k_th(b, deep[b]-deep[a]);
		if(a==b) return a;
		for(int i=20; i>=0; i--){
			if(p[a][i]!=p[b][i]) a=p[a][i], b=p[b][i];
		}
		return p[a][0];
	}
} lca;

int find(int u) {return root[u] == u ? u : root[u] = find(root[u]);}

int solve() {
	cin >> n >> m >> k >> q;
	for(int i=0; i<m; i++) {
		int u, v, w;
		scanf("%d %d %d", &u, &v, &w);
		adj[u].pb({v, w});
		adj[v].pb({u, w});
	}
	for(int i=1; i<=k; i++) s.insert({0, i}), fa[i] = i;
	for(int i=k+1; i<=n; i++) s.insert({dst[i] = inf, i});
	for(int i=1; i<=n; i++) {
		pii tmp = *s.begin();
		s.erase(s.begin());
		int u = tmp.y;
		INT d = tmp.x;
		for(auto p : adj[u]) {
			int v = p.x;
			int w = p.y;
			if(dst[v] > d + w) {
				s.erase({dst[v], v});
				s.insert({dst[v] = d + w, v});
				fa[v] = fa[u];
			}
		}
	}
	vector<ppi> edge;

	for(int u=1; u<=n; u++) {
		for(auto p : adj[u]) {
			int v = p.x;
			int w = p.y;
			if(u<v) continue;
			if(fa[v] != fa[u]) {
				int uu = fa[u];
				int vv = fa[v];
				edge.pb({{uu, vv}, dst[u] + dst[v] + w});
			}
		}
	}
	sort(edge.begin(), edge.end(), [](ppi u, ppi v) {
		return u.y < v.y;
	});
	for(int i=1; i<=k; i++) root[i] = i;
	int nn = k;
	for(auto p : edge) {
		int u=p.x.x, v = p.x.y;
		u = find(u); v = find(v);
		if(u != v) {
			++nn;
			tmp[nn].pb(u);
			tmp[nn].pb(v);
			root[u] = nn;
			root[v] = nn;
			root[nn] = nn;
			val[nn] = p.y;
		}
	}
	lca.dfs(nn);
	while(q--) {
		int u, v;
		scanf("%d %d", &u, &v);
		printf("%I64d\n", val[lca.lca(u, v)]);
	}
}
int main() {
#ifndef	ONLINE_JUDGE
	freopen("in.in", "r", stdin);
	freopen("out.out", "w", stdout);
#endif
	solve();
	return 0;
}


#include <bits/stdc++.h>

#define x first
#define y second

using namespace std;
using INT = long long;
using pii = pair<int, int>;

const int NN=600030, M = 20;

int dep[NN], p[NN][20], rt[NN];
vector<int> tadj[NN];
vector<pii> adj[NN];
INT dst[NN], val[NN];

void dfs(int u, int pa=0) {
	p[u][0]=pa; dep[u]=dep[pa]+1;
	for (int i=1; i<M; i++) p[u][i]=p[p[u][i-1]][i-1];
	for (int v : tadj[u]) dfs(v, u);
}

int k_th(int u, int k) {
	while (k) {
		int v=__lg(k);
		u=p[u][v];
		k^=1<<v;
	}
	return u;
}

int lca(int u, int v) {
	if (dep[u]>dep[v]) swap(u, v);
	v=k_th(v, dep[v]-dep[u]);
	if (u==v) return u;
	for (int t=M; t--; ) {
		if (p[u][t]!=p[v][t]) u=p[u][t], v=p[u][t];
	}
	return p[u][0];
}

int find(int u) {return rt[u]==u?u:rt[u]=find(rt[u]);}

int main(){
#ifndef ONLINE_JUDGE
	freopen("in.in", "r", stdin);
	freopen("out.out", "w", stdout);
#endif

	int n, m, K, Q, u, v, w;
	cin>>n>>m>>K>>Q;
	for (int i=0; i<m; i++) {
		scanf("%d%d%d", &u, &v, &w);
		adj[u].emplace_back(v, w);
		adj[v].emplace_back(u, w);
	}

	memset(dst, 0x3f, sizeof dst);
	set<pair<INT, int>> st;
	for (int i=1; i<=K; i++) st.insert({dst[i]=0, i}), rt[i]=i;
	for (int i=1; i<=n; i++) {
		int u=st.begin()->y; st.erase(st.begin());
		for (auto t : adj[u]) {
			if (dst[t.x]>dst[u]+t.y) {
				st.erase({dst[t.x], t.x});
				dst[t.x]=dst[u]+t.y; rt[t.x]=rt[u];
				st.insert({dst[t.x], t.x});
			}
		}
	}

	vector<pair<INT, pii>> edge;
	for (int i=1; i<=n; i++) {
		for (auto t : adj[i]) {
			int u=rt[i], v=rt[t.x];
			if (u==v) continue;
			edge.emplace_back(dst[i]+dst[t.x]+t.y, pii(u, v));
		}
	}
	sort(edge.begin(), edge.end());

	int N = K;
	for (auto t : edge) {
		int u=find(t.y.x), v=find(t.y.y);
		if (u==v) continue;
		rt[N]=++N;
		tadj[N].push_back(u);
		tadj[N].push_back(v);
		rt[u]=rt[v]=N; val[N]=t.x;
	}
	dfs(N);
	while (Q--) {
		scanf("%d%d", &u, &v);
		printf("%I64d\n", val[lca(u, v)]);
	}

	return 0;
}


#include <bits/stdc++.h>

#define x first
#define y second

using namespace std;
using INT = long long;
using pii = pair<int, int>;

const int NN=600030, M = 20;

int dep[NN], p[NN][20], rt[NN];
vector<int> tadj[NN];
vector<pii> adj[NN];
INT dst[NN], val[NN];

void dfs(int u, int pa=0) {
	p[u][0]=pa; dep[u]=dep[pa]+1;
	for (int i=1; i<M; i++) p[u][i]=p[p[u][i-1]][i-1];
	for (int v : tadj[u]) dfs(v, u);
}

int k_th(int u, int k) {
	while (k) {
		int v=__lg(k);
		u=p[u][v];
		k^=1<<v;
	}
	return u;
}

int lca(int u, int v) {
	if (dep[u]>dep[v]) swap(u, v);
	v=k_th(v, dep[v]-dep[u]);
	if (u==v) return u;
	for (int t=M; t--; ) {
		if (p[u][t]!=p[v][t]) u=p[u][t], v=p[u][t];
		if (p[u][0]==p[v][0]) break;
	}
	return p[u][0];
}

int find(int u) {return rt[u]==u?u:rt[u]=find(rt[u]);}

int main(){
#ifndef ONLINE_JUDGE
	freopen("in.in", "r", stdin);
	freopen("out.out", "w", stdout);
#endif

	int n, m, K, Q, u, v, w;
	cin>>n>>m>>K>>Q;
	for (int i=0; i<m; i++) {
		scanf("%d%d%d", &u, &v, &w);
		adj[u].emplace_back(v, w);
		adj[v].emplace_back(u, w);
	}

	memset(dst, 0x3f, sizeof dst);
	set<pii> st;
	for (int i=1; i<=K; i++) st.insert({dst[i]=0, i}), rt[i]=i;
	for (int i=1; i<=n; i++) {
		int u=st.begin()->y; st.erase(st.begin());
		for (auto t : adj[u]) {
			if (dst[t.x]>dst[u]+t.y) {
				st.erase({dst[t.x], t.x});
				dst[t.x]=dst[u]+t.y; rt[t.x]=rt[u];
				st.insert({dst[t.x], t.x});
			}
		}
	}

	vector<pair<INT, pii>> edge;
	for (int i=1; i<=n; i++) {
		for (auto t : adj[i]) {
			int u=rt[i], v=rt[t.x];
			if (u==v) continue;
			edge.emplace_back(dst[i]+dst[t.x]+t.y, pii(u, v));
		}
	}
	sort(edge.begin(), edge.end());

	int N = K;
	for (auto t : edge) {
		int u=find(t.y.x), v=find(t.y.y);
		if (u==v) continue;
		rt[N]=++N;
		tadj[N].push_back(u);
		tadj[N].push_back(v);
		rt[u]=rt[v]=N; val[N]=t.x;
	}
	dfs(N);
	while (Q--) {
		scanf("%d%d", &u, &v);
		printf("%I64d\n", val[lca(u, v)]);
	}

	return 0;
}


#include <bits/stdc++.h>

#define x first
#define y second

using namespace std;
using INT = long long;
using pii = pair<int, int>;

const int NN=600030, M = 20;

int dep[NN], p[NN][20], rt[NN];
vector<int> tadj[NN];
vector<pii> adj[NN];
INT dst[NN], val[NN];

void dfs(int u, int pa=0) {
	p[u][0]=pa; dep[u]=dep[pa]+1;
	for (int i=1; i<M; i++) p[u][i]=p[p[u][i-1]][i-1];
	for (int v : tadj[u]) dfs(v, u);
}

int k_th(int u, int k) {
	while (k) {
		int v=__lg(k);
		u=p[u][v];
		k^=1<<v;
	}
	return u;
}

int lca(int u, int v) {
	if (dep[u]>dep[v]) swap(u, v);
	v=k_th(v, dep[v]-dep[u]);
	if (u==v) return u;
	for (int t=M; t--; ) {
		if (p[u][t]!=p[v][t]) u=p[u][t], v=p[u][t];
	}
	return p[u][0];
}

int find(int u) {return rt[u]==u?u:rt[u]=find(rt[u]);}

int main(){
#ifndef ONLINE_JUDGE
	freopen("in.in", "r", stdin);
	freopen("out.out", "w", stdout);
#endif

	int n, m, K, Q, u, v, w;
	cin>>n>>m>>K>>Q;
	for (int i=0; i<m; i++) {
		scanf("%d%d%d", &u, &v, &w);
		adj[u].emplace_back(v, w);
		adj[v].emplace_back(u, w);
	}

	memset(dst, 0x3f, sizeof dst);
	set<pii> st;
	for (int i=1; i<=K; i++) st.insert({dst[i]=0, i}), rt[i]=i;
	for (int i=K+1; i<=n; i++) st.insert({dst[i], i});
	for (int i=1; i<=n; i++) {
		int u=st.begin()->y; st.erase(st.begin());
		for (auto t : adj[u]) {
			if (dst[t.x]>dst[u]+t.y) {
				st.erase({dst[t.x], t.x});
				dst[t.x]=dst[u]+t.y; rt[t.x]=rt[u];
				st.insert({dst[t.x], t.x});
			}
		}
	}

	vector<pair<INT, pii>> edge;
	for (int i=1; i<=n; i++) {
		for (auto t : adj[i]) {
			int u=rt[i], v=rt[t.x];
			if (u==v) continue;
			edge.emplace_back(dst[i]+dst[t.x]+t.y, pii(u, v));
		}
	}
	sort(edge.begin(), edge.end());

	int N = K; 	for (auto t : edge) {
		int u=find(t.y.x), v=find(t.y.y);
		if (u==v) continue;
		rt[N]=++N;
		tadj[N].push_back(u);
		tadj[N].push_back(v);
		rt[u]=rt[v]=N; val[N]=t.x;
	}
	dfs(N);
	while (Q--) {
		scanf("%d%d", &u, &v);
		printf("%I64d\n", val[lca(u, v)]);
	}

	return 0;
}


#include <bits/stdc++.h>

#define x first
#define y second

using namespace std;
using INT = long long;
using pii = pair<INT, INT>;

const int NN=600030, M = 21;

int dep[NN], p[NN][M], rt[NN];
vector<INT> tadj[NN];
vector<pii> adj[NN];
INT dst[NN], val[NN];

void dfs(int u, int pa=0) {
	p[u][0]=pa; dep[u]=dep[pa]+1;
	for (int i=1; i<M; i++) p[u][i]=p[p[u][i-1]][i-1];
	for (int v : tadj[u]) dfs(v, u);
}

int k_th(int u, int k) {
	while (k) {
		u=p[u][__builtin_ctz(k)];
		k^=k&-k;
	}
	return u;
}

int lca(int u, int v) {
	if (dep[u]>dep[v]) swap(u, v);
	v=k_th(v, dep[v]-dep[u]);
	if (u==v) return u;
	for (int t=M; t--; ) {
		if (p[u][t]!=p[v][t]) u=p[u][t], v=p[u][t];
	}
	return p[u][0];
}

int find(int u) {return rt[u]==u?u:rt[u]=find(rt[u]);}

int main(){
#ifndef ONLINE_JUDGE
	freopen("in.in", "r", stdin);
	freopen("out.out", "w", stdout);
#endif

	int n, m, K, Q, u, v, w;
	cin>>n>>m>>K>>Q;
	for (int i=0; i<m; i++) {
		scanf("%d%d%d", &u, &v, &w);
		adj[u].emplace_back(v, w);
		adj[v].emplace_back(u, w);
	}

	memset(dst, 0x3f, sizeof dst);
	set<pair<INT, int>> st;
	for (int i=1; i<=K; i++) st.insert({dst[i]=0, i}), rt[i]=i;
	for (int i=K+1; i<=n; i++) st.insert({dst[i], i});
	for (int i=1; i<=n; i++) {
		int u=st.begin()->y; st.erase(st.begin());
		for (auto t : adj[u]) {
			if (dst[t.x]>dst[u]+t.y) {
				st.erase({dst[t.x], t.x});
				rt[t.x]=rt[u];
				st.insert({dst[t.x]=dst[u]+t.y, t.x});
			}
		}
	}

	vector<pair<INT, pii>> edge;
	for (int i=1; i<=n; i++) {
		for (auto t : adj[i]) if (i>t.x) {
			int u=rt[i], v=rt[t.x];
			if (u==v) continue;
			edge.emplace_back(dst[i]+dst[t.x]+t.y, pii(u, v));
		}
	}
	sort(edge.begin(), edge.end());

	int N = K;
	for (auto t : edge) {
		int u=find(t.y.x), v=find(t.y.y);
		if (u==v) continue;
		++N;
		tadj[N].push_back(u);
		tadj[N].push_back(v);
		rt[u]=rt[v]=rt[N]=N; val[N]=t.x;
	}
	dfs(N);
	while (Q--) {
		scanf("%d%d", &u, &v);
		printf("%I64d\n", val[lca(u, v)]);
	}

	return 0;
}


#include <bits/stdc++.h>

#define x first
#define y second

using namespace std;
using INT = long long;
using pii = pair<INT, INT>;

const int NN=600030, M = 21;

int dep[NN], p[NN][M], rt[NN], fa[NN];
vector<INT> tadj[NN];
vector<pii> adj[NN];
INT dst[NN], val[NN];

void dfs(int u, int pa=0) {
	p[u][0]=pa; dep[u]=dep[pa]+1;
	for (int i=1; i<M; i++) p[u][i]=p[p[u][i-1]][i-1];
	for (int v : tadj[u]) dfs(v, u);
}

int k_th(int u, int k) {
	while (k) {
		u=p[u][__builtin_ctz(k)];
		k^=k&-k;
	}
	return u;
}

int lca(int u, int v) {
	if (dep[u]>dep[v]) swap(u, v);
	v=k_th(v, dep[v]-dep[u]);
	if (u==v) return u;
	for (int t=M; t--; ) {
		if (p[u][t]!=p[v][t]) u=p[u][t], v=p[v][t];
	}
	return p[u][0];
}

int find(int u) {return rt[u]==u?u:rt[u]=find(rt[u]);}

int main(){
#ifndef ONLINE_JUDGE
	freopen("in.in", "r", stdin);
	freopen("out.out", "w", stdout);
#endif

	int n, m, K, Q, u, v, w;
	cin>>n>>m>>K>>Q;
	for (int i=0; i<m; i++) {
		scanf("%d%d%d", &u, &v, &w);
		adj[u].emplace_back(v, w);
		adj[v].emplace_back(u, w);
	}

	for (int i=K+1; i<=n; i++) dst[i]=1LL<<60;
	set<pair<INT, INT>> st;
	for (int i=1; i<=n; i++) st.insert({dst[i], i});
	for (int i=1; i<=K; i++) fa[i]=i;
	for (int i=1; i<=n; i++) {
		int u=st.begin()->y; st.erase(st.begin());
		for (auto t : adj[u]) {
			if (dst[t.x]>dst[u]+t.y) {
				st.erase({dst[t.x], t.x});
				fa[t.x]=fa[u];
				st.insert({dst[t.x]=dst[u]+t.y, t.x});
			}
		}
	}

	vector<pair<INT, pii>> edge;
	for (int i=1; i<=n; i++) {
		for (auto t : adj[i]) if (i>t.x) {
			int u=fa[i], v=fa[t.x];
			if (u==v) continue;
			edge.emplace_back(dst[i]+dst[t.x]+t.y, pii(u, v));
		}
	}
	sort(edge.begin(), edge.end());

	int N = K;
	for (int i=1; i<=K; i++) rt[i]=i;
	for (auto t : edge) {
		int u=find(t.y.x), v=find(t.y.y);
		if (u==v) continue;
		++N;
		tadj[N].push_back(u);
		tadj[N].push_back(v);
		rt[u]=rt[v]=rt[N]=N; val[N]=t.x;
	}
	dfs(N);
	while (Q--) {
		scanf("%d%d", &u, &v);
		printf("%I64d\n", val[lca(u, v)]);
	}

	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define ff first
#define ss second
#define INF 1e16;
typedef long long ll;
ll mod = 1e9+7;
ll fast_exp(ll a, ll b)
{
    if(b == 0)
	   return 1;
    else
    {
	   ll res = 1;
	   res = fast_exp(a,b/2);
	   res = (res*res)%mod;
	   if(b%2 == 1)
		  res = (res*a)%mod;
	   return res;

    }
}

const ll N = 1e5+10;
vector <pair<ll,ll>> edge[N];
vector <pair<ll,ll>> modedge[N];
ll par[N];
ll dist[N];
ll size[N];
ll find_set(ll a)
{
	if(par[a] == a)
		return a;
	else
		return par[a] = find_set(par[a]);
}
void make_set(int v) {
    par[v] = v;
    size[v] = 1;
}

void union_find(int a, int b) {
    a = find_set(a);
    b = find_set(b);
    if (a != b) {
        if (size[a] < size[b])
            swap(a, b);
        par[b] = a;
        size[a] += size[b];
    }
}
ll depth[N];
ll jump[N][25];
ll val[N][25];
int vis[N]={};
void dfs(ll v, ll par,ll dep)
{
	vis[v] = 1;
	depth[v] = dep;
	for(auto e: modedge[v])
	{
		if(e.ff!=par && !vis[e.ff])
			{
				jump[e.ff][0] = v;
				val[e.ff][0] = e.ss;
				dfs(e.ff,v,dep+1);
			}
	}
}

ll lca_query(ll a, ll b)
{
	if(depth[a]<depth[b])
		swap(a,b);
	ll jcount = 20;
	ll mupto = 0;
	//cout<<"a: "<<a<<"  b: "<<b<<endl;

	while(depth[a]!=depth[b])
	{
		//cout<<"jcount : "<<jcount<<endl;
		//cout<<"a: "<<a<<"  b: "<<b<<endl;
		int c = jump[a][jcount];
		//cout<<" c:"<<c<<" depth[c]: "<<depth[c]<<"depth[b]: "<<depth[b]<<'\n';
		if(depth[jump[a][jcount]] < depth[b])
			jcount--;
		else
		{
			mupto = max(mupto,val[a][jcount]);
			a = jump[a][jcount];

		}
		//cout<<"after\n";
		//cout<<"a: "<<a<<"  b: "<<b<<endl;

	}
	if(a != b)
	{
		for(ll jpow = 20 ; jpow>=0 ; jpow--)
			if(jump[a][jpow] != jump[b][jpow])
			{
				//cout<<"jpow : "<<jpow<<endl;
				//cout<<"jmpa : "<<jump[a][jpow]<<"   jmpb : "<<jump[b][jpow]<<endl;
				mupto = max(mupto,val[a][jpow]);
				mupto = max(mupto,val[b][jpow]);
				a = jump[a][jpow];
				b = jump[b][jpow];
				//cout<<"a: "<<a<<"  b: "<<b<<endl;

			}
		mupto = max(mupto,val[a][0]);
		mupto = max(mupto,val[b][0]);
	}

	return mupto;

}

int main()
{
	//ios_base::sync_with_stdio(false);
	//cin.tie(NULL);
	ll n,m,k,q,u,v,w;
	cin >> n >> m >> k >> q;
	vector<pair<ll,pair<ll,ll>> > krus;
	for(ll i = 0; i<m ; i++)
	{
		cin>> u >> v >> w;
		edge[u].pb({v,w});
		edge[v].pb({u,w});
		krus.pb(mp(w,mp(u,v)));
	}
	priority_queue < pair<ll,ll>, vector <pair<ll,ll>>, greater<pair<ll,ll>> > pq;

	for(ll i = 1; i<=n ; i++)
	{
		make_set(i);
		if(i<=k)
			dist[i] = 0;
		else
			dist[i] = INF;

		pq.push(mp(dist[i],i));
	}
	while(!pq.empty())
	{
		pair<ll,ll> topmin = pq.top();
		pq.pop();
		if(topmin.ff != dist[topmin.ss])
			continue;
		ll cur = topmin.ss;

		for(auto e: edge[cur])
		{
			if(dist[e.ff] > dist[cur] + e.ss)
			{
				//cout<<"relaxing : "<<e.ff<<"  d: "<<dist[e.ff]<<" rep by : "<<dist[cur] + e.ss<<"cur : "<<cur<<" dist[cur] = "<<dist[cur]<<endl;
				dist[e.ff] = dist[cur] + e.ss;
				pq.push(mp(dist[e.ff],e.ff));

			}
		}

	}
	// for(int i=1; i<=n ; i++)
	// 	cout<<"d : "<<dist[i]<<endl;
	for(ll i = 0; i<krus.size() ; i++)
	{
		ll v1 = krus[i].ss.ff , v2 = krus[i].ss.ss;
		krus[i].ff += dist[v1]+dist[v2];
	}
	sort(krus.begin(),krus.end());

	for(ll i = 0; i<krus.size(); i++)
	{
		ll v1 = krus[i].ss.ff;
		ll v2 = krus[i].ss.ss;
		ll weight = krus[i].ff;
		if(find_set(v2) != find_set(v1))
		{
			union_find(v2,v1);
			modedge[v2].pb(mp(v1,weight));
			modedge[v1].pb(mp(v2,weight));

			//cout<<"added : "<<v1<<" "<<v2<<"  "<<weight<<endl;
		}
	}
	for(ll i=0; i<25 ; i++)
	{
		jump[1][i] = 1;
		val[1][i] = 0;
	}
	dfs(1,-1,0);
	for(ll k = 1; k<25 ; k++)
	{
		for(ll i=1; i<=n ; i++)
		{
			jump[i][k] = jump[jump[i][k-1]][k-1];
			val[i][k] = max(val[i][k-1],val[jump[i][k-1]][k-1]);
		}
	}
	// for(int i=1; i<=n ; i++)
	// {
	// 	cout<<"for : "<<i<<endl;
	// 	for(int j = 0; j<10 ; j++)
	// 		cout<<j<<" : "<<val[i][j]<<endl;
	// }

	while(q--)
	{
		ll a, b;
		cin>>a>>b;

		cout<<lca_query(a,b)<<endl;

	}

	return 0;

}


#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define ff first
#define ss second
#define INF 1e16;
typedef long long ll;
ll mod = 1e9+7;
ll fast_exp(ll a, ll b)
{
    if(b == 0)
	   return 1;
    else
    {
	   ll res = 1;
	   res = fast_exp(a,b/2);
	   res = (res*res)%mod;
	   if(b%2 == 1)
		  res = (res*a)%mod;
	   return res;

    }
}

const ll N = 1e5+10;
vector <pair<ll,ll>> edge[N];
vector <pair<ll,ll>> modedge[N];
ll par[N];
ll dist[N];
ll find_set(ll a)
{
	if(par[a] == a)
		return a;
	else
		return par[a] = find_set(par[a]);
}
void union_find(ll a, ll b)
{
	a = find_set(a);
	b = find_set(b);
	if(a!=b)
		par[a] = b;
	return;
}
ll depth[N];
ll jump[N][25];
ll val[N][25];
int vis[N]={};
void dfs(ll v, ll par,ll dep)
{
	vis[v] = 1;
	depth[v] = dep;
	for(auto e: modedge[v])
	{
		if(e.ff!=par && !vis[e.ff])
			{
				jump[e.ff][0] = v;
				val[e.ff][0] = e.ss;
				dfs(e.ff,v,dep+1);
			}
	}
}

ll lca_query(ll a, ll b)
{
	if(depth[a]<depth[b])
		swap(a,b);
	ll jcount = 20;
	ll mupto = 0;
	//cout<<"a: "<<a<<"  b: "<<b<<endl;

	while(depth[a]!=depth[b])
	{
		//cout<<"jcount : "<<jcount<<endl;
		//cout<<"a: "<<a<<"  b: "<<b<<endl;
		int c = jump[a][jcount];
		//cout<<" c:"<<c<<" depth[c]: "<<depth[c]<<"depth[b]: "<<depth[b]<<'\n';
		if(depth[jump[a][jcount]] < depth[b])
			jcount--;
		else
		{
			mupto = max(mupto,val[a][jcount]);
			a = jump[a][jcount];

		}
		//cout<<"after\n";
		//cout<<"a: "<<a<<"  b: "<<b<<endl;

	}
	if(a != b)
	{
		for(ll jpow = 20 ; jpow>=0 ; jpow--)
			if(jump[a][jpow] != jump[b][jpow])
			{
				//cout<<"jpow : "<<jpow<<endl;
				//cout<<"jmpa : "<<jump[a][jpow]<<"   jmpb : "<<jump[b][jpow]<<endl;
				mupto = max(mupto,val[a][jpow]);
				mupto = max(mupto,val[b][jpow]);
				a = jump[a][jpow];
				b = jump[b][jpow];
				//cout<<"a: "<<a<<"  b: "<<b<<endl;

			}
		mupto = max(mupto,val[a][0]);
		mupto = max(mupto,val[b][0]);
	}

	return mupto;

}

int main()
{
	//ios_base::sync_with_stdio(false);
	//cin.tie(NULL);
	ll n,m,k,q,u,v,w;
	cin >> n >> m >> k >> q;
	vector<pair<ll,pair<ll,ll>> > krus;
	for(ll i = 0; i<m ; i++)
	{
		cin>> u >> v >> w;
		edge[u].pb({v,w});
		edge[v].pb({u,w});
		krus.pb(mp(w,mp(u,v)));
	}
	priority_queue < pair<ll,ll>, vector <pair<ll,ll>>, greater<pair<ll,ll>> > pq;

	for(ll i = 1; i<=n ; i++)
	{
		par[i] = i;
		if(i<=k)
			dist[i] = 0;
		else
			dist[i] = INF;

		pq.push(mp(dist[i],i));
	}
	while(!pq.empty())
	{
		pair<ll,ll> topmin = pq.top();
		pq.pop();
		if(topmin.ff != dist[topmin.ss])
			continue;
		ll cur = topmin.ss;

		for(auto e: edge[cur])
		{
			if(dist[e.ff] > dist[cur] + e.ss)
			{
				//cout<<"relaxing : "<<e.ff<<"  d: "<<dist[e.ff]<<" rep by : "<<dist[cur] + e.ss<<"cur : "<<cur<<" dist[cur] = "<<dist[cur]<<endl;
				dist[e.ff] = dist[cur] + e.ss;
				pq.push(mp(dist[e.ff],e.ff));

			}
		}

	}
	// for(int i=1; i<=n ; i++)
	// 	cout<<"d : "<<dist[i]<<endl;
	for(ll i = 0; i<krus.size() ; i++)
	{
		ll v1 = krus[i].ss.ff , v2 = krus[i].ss.ss;
		krus[i].ff += dist[v1]+dist[v2];
	}
	sort(krus.begin(),krus.end());

	for(ll i = 0; i<krus.size(); i++)
	{
		ll v1 = krus[i].ss.ff;
		ll v2 = krus[i].ss.ss;
		ll weight = krus[i].ff;
		if(find_set(v2) != find_set(v1))
		{
			union_find(v2,v1);
			modedge[v2].pb(mp(v1,weight));
			modedge[v1].pb(mp(v2,weight));

			//cout<<"added : "<<v1<<" "<<v2<<"  "<<weight<<endl;
		}
	}
	for(ll i=0; i<25 ; i++)
	{
		jump[1][i] = 1;
		val[1][i] = 0;
	}
	dfs(1,-1,0);
	for(ll k = 1; k<25 ; k++)
	{
		for(ll i=1; i<=n ; i++)
		{
			jump[i][k] = jump[jump[i][k-1]][k-1];
			val[i][k] = max(val[i][k-1],val[jump[i][k-1]][k-1]);
		}
	}
	// for(int i=1; i<=n ; i++)
	// {
	// 	cout<<"for : "<<i<<endl;
	// 	for(int j = 0; j<10 ; j++)
	// 		cout<<j<<" : "<<val[i][j]<<endl;
	// }

	while(q--)
	{
		ll a, b;
		cin>>a>>b;

		cout<<lca_query(a,b)<<endl;

	}

	return 0;

}


#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define ff first
#define ss second
#define INF 1e16;
typedef long long ll;
ll mod = 1e9+7;
ll fast_exp(ll a, ll b)
{
    if(b == 0)
	   return 1;
    else
    {
	   ll res = 1;
	   res = fast_exp(a,b/2);
	   res = (res*res)%mod;
	   if(b%2 == 1)
		  res = (res*a)%mod;
	   return res;

    }
}

const ll N = 1e5+10;
vector <pair<ll,ll>> edge[N];
vector <pair<ll,ll>> modedge[N];
ll par[N];
ll dist[N];
ll size[N];
ll find_set(ll a)
{
	if(par[a] == a)
		return a;
	else
		return par[a] = find_set(par[a]);
}
void make_set(int v) {
    par[v] = v;
    size[v] = 1;
}

void union_find(int a, int b) {
    a = find_set(a);
    b = find_set(b);
    if (a != b) {
        if (size[a] < size[b])
            swap(a, b);
        par[b] = a;
        size[a] += size[b];
    }
}
ll depth[N];
ll jump[N][25];
ll val[N][25];
int vis[N]={};
void dfs(ll v, ll par,ll dep)
{
	vis[v] = 1;
	depth[v] = dep;
	for(auto e: modedge[v])
	{
		if(e.ff!=par && !vis[e.ff])
			{
				jump[e.ff][0] = v;
				val[e.ff][0] = e.ss;
				dfs(e.ff,v,dep+1);
			}
	}
}

ll lca_query(ll a, ll b)
{
	if(depth[a]<depth[b])
		swap(a,b);
	ll jcount = 20;
	ll mupto = 0;
	//cout<<"a: "<<a<<"  b: "<<b<<endl;

	while(depth[a]!=depth[b])
	{
		//cout<<"jcount : "<<jcount<<endl;
		//cout<<"a: "<<a<<"  b: "<<b<<endl;
		int c = jump[a][jcount];
		//cout<<" c:"<<c<<" depth[c]: "<<depth[c]<<"depth[b]: "<<depth[b]<<'\n';
		if(depth[jump[a][jcount]] < depth[b])
			jcount--;
		else
		{
			mupto = max(mupto,val[a][jcount]);
			a = jump[a][jcount];

		}
		//cout<<"after\n";
		//cout<<"a: "<<a<<"  b: "<<b<<endl;

	}
	if(a != b)
	{
		for(ll jpow = 20 ; jpow>=0 ; jpow--)
			if(jump[a][jpow] != jump[b][jpow])
			{
				//cout<<"jpow : "<<jpow<<endl;
				//cout<<"jmpa : "<<jump[a][jpow]<<"   jmpb : "<<jump[b][jpow]<<endl;
				mupto = max(mupto,val[a][jpow]);
				mupto = max(mupto,val[b][jpow]);
				a = jump[a][jpow];
				b = jump[b][jpow];
				//cout<<"a: "<<a<<"  b: "<<b<<endl;

			}
		mupto = max(mupto,val[a][0]);
		mupto = max(mupto,val[b][0]);
	}

	return mupto;

}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	ll n,m,k,q,u,v,w;
	cin >> n >> m >> k >> q;
	vector<pair<ll,pair<ll,ll>> > krus;
	for(ll i = 0; i<m ; i++)
	{
		cin>> u >> v >> w;
		edge[u].pb({v,w});
		edge[v].pb({u,w});
		krus.pb(mp(w,mp(u,v)));
	}
	priority_queue < pair<ll,ll>, vector <pair<ll,ll>>, greater<pair<ll,ll>> > pq;

	for(ll i = 1; i<=n ; i++)
	{
		make_set(i);
		if(i<=k)
			dist[i] = 0;
		else
			dist[i] = INF;

		pq.push(mp(dist[i],i));
	}
	while(!pq.empty())
	{
		pair<ll,ll> topmin = pq.top();
		pq.pop();
		if(topmin.ff != dist[topmin.ss])
			continue;
		ll cur = topmin.ss;

		for(auto e: edge[cur])
		{
			if(dist[e.ff] > dist[cur] + e.ss)
			{
				//cout<<"relaxing : "<<e.ff<<"  d: "<<dist[e.ff]<<" rep by : "<<dist[cur] + e.ss<<"cur : "<<cur<<" dist[cur] = "<<dist[cur]<<endl;
				dist[e.ff] = dist[cur] + e.ss;
				pq.push(mp(dist[e.ff],e.ff));

			}
		}

	}
	// for(int i=1; i<=n ; i++)
	// 	cout<<"d : "<<dist[i]<<endl;
	for(ll i = 0; i<krus.size() ; i++)
	{
		ll v1 = krus[i].ss.ff , v2 = krus[i].ss.ss;
		krus[i].ff += dist[v1]+dist[v2];
	}
	sort(krus.begin(),krus.end());

	for(ll i = 0; i<krus.size(); i++)
	{
		ll v1 = krus[i].ss.ff;
		ll v2 = krus[i].ss.ss;
		ll weight = krus[i].ff;
		if(find_set(v2) != find_set(v1))
		{
			union_find(v2,v1);
			modedge[v2].pb(mp(v1,weight));
			modedge[v1].pb(mp(v2,weight));

			//cout<<"added : "<<v1<<" "<<v2<<"  "<<weight<<endl;
		}
	}
	for(ll i=0; i<25 ; i++)
	{
		jump[1][i] = 1;
		val[1][i] = 0;
	}
	dfs(1,-1,0);
	for(ll k = 1; k<25 ; k++)
	{
		for(ll i=1; i<=n ; i++)
		{
			jump[i][k] = jump[jump[i][k-1]][k-1];
			val[i][k] = max(val[i][k-1],val[jump[i][k-1]][k-1]);
		}
	}
	// for(int i=1; i<=n ; i++)
	// {
	// 	cout<<"for : "<<i<<endl;
	// 	for(int j = 0; j<10 ; j++)
	// 		cout<<j<<" : "<<val[i][j]<<endl;
	// }

	while(q--)
	{
		ll a, b;
		cin>>a>>b;

		cout<<lca_query(a,b)<<endl;

	}

	return 0;

}


#include <bits/stdc++.h>
#define ll long long
#define nmax 200010

using namespace std;
struct node
{
    int u,v; ll w;
    node() {u=v=w=0;}
    node(ll x,ll y,ll z) {u=x;v=y;w=z;}
};
bool cmp(const node &a,const node &b)
{
    return (a.w<b.w);
}
int n,m,k,test,g[nmax],p[nmax],lab[nmax],h[nmax];
ll d[nmax];
pair<int,ll> f[nmax][30];
vector<pair<int,ll> > vt[nmax];
vector<pair<int,ll> > vt1[nmax];
priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > > q;
ll find(ll r)
{
    if (r!=p[r]) return p[r]=find(p[r]);
    return p[r];
}
bool unite(ll x,ll y)
{
    x=find(x); y=find(y);
    if (x==y) return 0;
    if (lab[x]==lab[y]) lab[x]++;

    if (lab[x]<lab[y]) p[x]=y;
    else p[y]=x;
    return 1;
}
void dfs(int u,int cha)
{
    for (int e=0;e<(int)vt1[u].size();e++)
    {
        int v=vt1[u][e].first; ll w=vt1[u][e].second;
        if (v==cha) continue;
        h[v]=h[u]+1; f[v][0]={u,w};
        dfs(v,u);
    }
}
ll tv(int x,int y)
{
    ll ans=0;
    for (int k=19;k>=0;k--)
    {
        int xm=f[x][k].first;
        if (h[xm]>=h[y])
        {
            ans=max(ans,f[x][k].second);
            x=xm;
        }
    }
    for (int k=19;k>=0;k--)
    {
        int ym=f[y][k].first;
        if (h[ym]>=h[x])
        {
            ans=max(ans,f[y][k].second);
            y=ym;
        }
    }

    for (int k=19;k>=0;k--)
        if (f[x][k].first!=f[y][k].first)
        {
            ans=max(ans,max(f[x][k].second,f[y][k].second));
            x=f[x][k].first; y=f[y][k].first;
        }

    while (x!=y)
    {
        ans=max(ans,max(f[x][0].second,f[y][0].second));
        x=f[x][0].first; y=f[y][0].first;
    }
    //cout<<ans<<" "<<them1<<" "<<them2<<'\n';
    return ans;//+them1+them2;
}
int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin>>n>>m>>k>>test;
    for (int i=1;i<=m;i++)
    {
        int u,v; ll w; cin>>u>>v>>w;
        vt[u].emplace_back(v,w); vt[v].emplace_back(u,w);
    }

    for (int i=1;i<=k;i++)
    {
        d[i]=0; g[i]=i;
        q.emplace(0,i);
    }
    for (int i=k+1;i<=n;i++) d[i]=1e18;

    while (!q.empty())
    {
        int u=q.top().second; q.pop();
        for (int e=0;e<(int)vt[u].size();e++)
        {
            int v=vt[u][e].first; ll w=vt[u][e].second;
            if (d[v]>d[u]+w)
            {
                d[v]=d[u]+w;
                g[v]=g[u];
                q.emplace(d[v],v);
            }
        }
    }

    //for (ll i=1;i<=n;i++) cout<<d[i]<<" "<<g[i]<<'\n';
    vector<node> canh;
    for (int i=1;i<=n;i++)
    {
        for (int e=0;e<(int)vt[i].size();e++)
        {
            int v=vt[i][e].first; ll w=vt[i][e].second;
            if (g[i]==g[v]) continue;
            canh.push_back(node(i,v,w+d[i]+d[v]));
        }
        //vt[i].clear();
    }

    sort(canh.begin(),canh.end(),cmp);
    for (int i=1;i<=k;i++) p[i]=i;

    for (int i=0;i<(int)canh.size();i++)
    {
        int u=g[canh[i].u]; int v=g[canh[i].v]; ll w=canh[i].w;
        if (unite(u,v))
        {
            vt1[u].emplace_back(v,w);
            vt1[v].emplace_back(u,w);
        }
    }

    f[1][0]={-1,0};
    dfs(1,-1);
    for (int j=1;j<=20;j++)
        for (int i=1;i<=k;i++)
        {
            f[i][j].first=f[f[i][j-1].first][j-1].first;
            f[i][j].second=max(f[i][j-1].second,f[f[i][j-1].first][j-1].second);
        }

    //for (ll i=1;i<=k;i++) cout<<kq[i]<<'\n';
    while (test--)
    {
        int x,y; cin>>x>>y;
        cout<<tv(x,y)<<'\n';//+kq[x]+kq[y]<<'\n';
    }
    return 0;
}


#include <bits/stdc++.h>
#define ll long long
#define nmax 310

using namespace std;
struct node
{
    ll  u,v,w;
    node() {u=v=w=0;}
    node(ll  x,ll  y,ll  z) {u=x;v=y;w=z;}
};
bool cmp(const node &a,const node &b)
{
    return (a.w<b.w);
}
ll  n,m,k,test,d[nmax],g[nmax],p[nmax],lab[nmax],h[nmax],kq[nmax];
pair<ll ,ll > f[nmax][30];
vector<pair<ll ,ll > > vt[nmax];
vector<pair<ll ,ll > > vt1[nmax];
priority_queue<pair<ll ,ll >,vector<pair<ll ,ll > >,greater<pair<ll ,ll > > > q;
ll  find(ll  r)
{
    if (r!=p[r]) return p[r]=find(p[r]);
    return p[r];
}
bool unite(ll  x,ll  y)
{
    x=find(x); y=find(y);
    if (x==y) return 0;
    if (lab[x]==lab[y]) lab[x]++;

    if (lab[x]<lab[y]) p[x]=y;
    else p[y]=x;
    return 1;
}
void dfs(ll  u,ll  cha)
{
    for (ll  e=0;e<(ll )vt[u].size();e++)
    {
        ll  v=vt[u][e].first; ll  w=vt[u][e].second;
        if (v==cha) continue;
        h[v]=h[u]+1; f[v][0]={u,w}; kq[v]=vt1[u][e].second;
        dfs(v,u);
    }
}
ll  tv(ll  x,ll  y)
{
    ll  ans=0; ll  them1=0,them2=0;
    for (ll  k=19;k>=0;k--)
    {
        ll  xm=f[x][k].first;
        if (h[xm]>=h[y])
        {
            ans=max(ans,f[x][k].second);
            if (them1==0) them1+=kq[x];
            x=xm;
        }
    }
    for (ll  k=19;k>=0;k--)
    {
        ll  ym=f[y][k].first;
        if (h[ym]>=h[x])
        {
            ans=max(ans,f[y][k].second);
            if (them2==0) them2+=kq[y];
            y=ym;
        }
    }

    for (ll  k=19;k>=0;k--)
        if (f[x][k].first!=f[y][k].first)
        {
            ans=max(ans,max(f[x][k].second,f[y][k].second));
            x=f[x][k].first; y=f[y][k].first;
        }

    while (x!=y)
    {
        ans=max(ans,max(f[x][0].second,f[y][0].second));
        x=f[x][0].first; y=f[y][0].first;
    }
    //cout<<ans<<" "<<them1<<" "<<them2<<'\n';
    return ans;//+them1+them2;
}
ll  main()
{
    cin>>n>>m>>k>>test;
    for (ll  i=1;i<=m;i++)
    {
        ll  u,v,w; cin>>u>>v>>w;
        vt[u].emplace_back(v,w); vt[v].emplace_back(u,w);
    }

    for (ll  i=1;i<=k;i++)
    {
        d[i]=0; g[i]=i;
        q.emplace(0,i);
    }
    for (ll  i=k+1;i<=n;i++) d[i]=1e9+1;

    while (!q.empty())
    {
        ll  u=q.top().second; q.pop();
        for (ll  e=0;e<(ll )vt[u].size();e++)
        {
            ll  v=vt[u][e].first; ll  w=vt[u][e].second;
            if (d[v]>d[u]+w)
            {
                d[v]=d[u]+w;
                g[v]=g[u];
                q.emplace(d[v],v);
                if (g[u]==1) kq[1]=max(kq[1],d[v]);
            }
        }
    }

    //for (ll  i=1;i<=n;i++) cout<<d[i]<<" "<<g[i]<<'\n';
    vector<node> canh;
    for (ll  i=1;i<=n;i++)
    {
        for (ll  e=0;e<(ll )vt[i].size();e++)
        {
            ll  v=vt[i][e].first; ll  w=vt[i][e].second;
            if (g[i]==g[v]) continue;
            canh.push_back(node(i,v,w+d[i]+d[v]));
        }
        vt[i].clear();
    }

    sort(canh.begin(),canh.end(),cmp);
    for (ll  i=1;i<=k;i++) p[i]=i;

    for (ll  i=0;i<(ll )canh.size();i++)
    {
        ll  u=g[canh[i].u]; ll  v=g[canh[i].v]; ll  w=canh[i].w;
        if (unite(u,v))
        {
            vt[u].emplace_back(v,w);
            vt[v].emplace_back(u,w);
            vt1[u].emplace_back(d[canh[i].u],d[canh[i].v]);
            vt1[v].emplace_back(d[canh[i].v],d[canh[i].u]);
        }
    }

    f[1][0]={-1,0};
    dfs(1,-1);
    for (ll  j=1;j<=20;j++)
        for (ll  i=1;i<=k;i++)
        {
            f[i][j].first=f[f[i][j-1].first][j-1].first;
            f[i][j].second=max(f[i][j-1].second,f[f[i][j-1].first][j-1].second);
        }

    //for (ll  i=1;i<=k;i++) cout<<kq[i]<<'\n';
    while (test--)
    {
        ll  x,y; cin>>x>>y;
        cout<<tv(x,y)<<'\n';//+kq[x]+kq[y]<<'\n';
    }
    return 0;
}


#include <bits/stdc++.h>
#define ll long long
#define nmax 200010

using namespace std;
struct node
{
    int u,v; ll w;
    node() {u=v=w=0;}
    node(ll x,ll y,ll z) {u=x;v=y;w=z;}
};
bool cmp(const node &a,const node &b)
{
    return (a.w<b.w);
}
int n,m,k,test,g[nmax],p[nmax],lab[nmax],h[nmax];
ll d[nmax];
pair<int,ll> f[nmax][30];
vector<pair<int,ll> > vt[nmax];
vector<pair<int,ll> > vt1[nmax];
priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > > q;
ll find(ll r)
{
    if (r!=p[r]) return p[r]=find(p[r]);
    return p[r];
}
bool unite(ll x,ll y)
{
    x=find(x); y=find(y);
    if (x==y) return 0;
    if (lab[x]==lab[y]) lab[x]++;

    if (lab[x]<lab[y]) p[x]=y;
    else p[y]=x;
    return 1;
}
void dfs(int u,int cha)
{
    for (int e=0;e<(ll)vt[u].size();e++)
    {
        int v=vt[u][e].first; ll w=vt[u][e].second;
        if (v==cha) continue;
        h[v]=h[u]+1; f[v][0]={u,w};
        dfs(v,u);
    }
}
ll tv(int x,int y)
{
    ll ans=0;
    for (int k=19;k>=0;k--)
    {
        int xm=f[x][k].first;
        if (h[xm]>=h[y])
        {
            ans=max(ans,f[x][k].second);
            x=xm;
        }
    }
    for (int k=19;k>=0;k--)
    {
        int ym=f[y][k].first;
        if (h[ym]>=h[x])
        {
            ans=max(ans,f[y][k].second);
            y=ym;
        }
    }

    for (int k=19;k>=0;k--)
        if (f[x][k].first!=f[y][k].first)
        {
            ans=max(ans,max(f[x][k].second,f[y][k].second));
            x=f[x][k].first; y=f[y][k].first;
        }

    while (x!=y)
    {
        ans=max(ans,max(f[x][0].second,f[y][0].second));
        x=f[x][0].first; y=f[y][0].first;
    }
    //cout<<ans<<" "<<them1<<" "<<them2<<'\n';
    return ans;//+them1+them2;
}
int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin>>n>>m>>k>>test;
    for (int i=1;i<=m;i++)
    {
        int u,v; ll w; cin>>u>>v>>w;
        vt[u].emplace_back(v,w); vt[v].emplace_back(u,w);
    }

    for (int i=1;i<=k;i++)
    {
        d[i]=0; g[i]=i;
        q.emplace(0,i);
    }
    for (int i=k+1;i<=n;i++) d[i]=1e18;

    while (!q.empty())
    {
        int u=q.top().second; q.pop();
        for (int e=0;e<(int)vt[u].size();e++)
        {
            int v=vt[u][e].first; ll w=vt[u][e].second;
            if (d[v]>d[u]+w)
            {
                d[v]=d[u]+w;
                g[v]=g[u];
                q.emplace(d[v],v);
                if (g[u]==1) kq[1]=max(kq[1],d[v]);
            }
        }
    }

    //for (ll i=1;i<=n;i++) cout<<d[i]<<" "<<g[i]<<'\n';
    vector<node> canh;
    for (int i=1;i<=n;i++)
    {
        for (int e=0;e<(ll)vt[i].size();e++)
        {
            int v=vt[i][e].first; ll w=vt[i][e].second;
            if (g[i]==g[v]) continue;
            canh.push_back(node(i,v,w+d[i]+d[v]));
        }
        vt[i].clear();
    }

    sort(canh.begin(),canh.end(),cmp);
    for (int i=1;i<=k;i++) p[i]=i;

    for (int i=0;i<(int)canh.size();i++)
    {
        int u=g[canh[i].u]; int v=g[canh[i].v]; ll w=canh[i].w;
        if (unite(u,v))
        {
            vt[u].emplace_back(v,w);
            vt[v].emplace_back(u,w);
            vt1[u].emplace_back(d[canh[i].u],d[canh[i].v]);
            vt1[v].emplace_back(d[canh[i].v],d[canh[i].u]);
        }
    }

    f[1][0]={-1,0};
    dfs(1,-1);
    for (int j=1;j<=20;j++)
        for (int i=1;i<=k;i++)
        {
            f[i][j].first=f[f[i][j-1].first][j-1].first;
            f[i][j].second=max(f[i][j-1].second,f[f[i][j-1].first][j-1].second);
        }

    //for (ll i=1;i<=k;i++) cout<<kq[i]<<'\n';
    while (test--)
    {
        int x,y; cin>>x>>y;
        cout<<tv(x,y)<<'\n';//+kq[x]+kq[y]<<'\n';
    }
    return 0;
}


#include <bits/stdc++.h>
#define lllong long
#define nmax 310

using namespace std;
struct node
{
    ll u,v,w;
    node() {u=v=w=0;}
    node(ll x,ll y,ll z) {u=x;v=y;w=z;}
};
bool cmp(const node &a,const node &b)
{
    return (a.w<b.w);
}
ll n,m,k,test,d[nmax],g[nmax],p[nmax],lab[nmax],h[nmax],kq[nmax];
pair<ll,ll> f[nmax][30];
vector<pair<ll,ll> > vt[nmax];
vector<pair<ll,ll> > vt1[nmax];
priority_queue<pair<ll,ll>,vector<pair<ll,ll> >,greater<pair<ll,ll> > > q;
ll find(ll r)
{
    if (r!=p[r]) return p[r]=find(p[r]);
    return p[r];
}
bool unite(ll x,ll y)
{
    x=find(x); y=find(y);
    if (x==y) return 0;
    if (lab[x]==lab[y]) lab[x]++;

    if (lab[x]<lab[y]) p[x]=y;
    else p[y]=x;
    return 1;
}
void dfs(ll u,ll cha)
{
    for (ll e=0;e<(ll)vt[u].size();e++)
    {
        ll v=vt[u][e].first; ll w=vt[u][e].second;
        if (v==cha) continue;
        h[v]=h[u]+1; f[v][0]={u,w}; kq[v]=vt1[u][e].second;
        dfs(v,u);
    }
}
ll tv(ll x,ll y)
{
    ll ans=0; ll them1=0,them2=0;
    for (ll k=19;k>=0;k--)
    {
        ll xm=f[x][k].first;
        if (h[xm]>=h[y])
        {
            ans=max(ans,f[x][k].second);
            if (them1==0) them1+=kq[x];
            x=xm;
        }
    }
    for (ll k=19;k>=0;k--)
    {
        ll ym=f[y][k].first;
        if (h[ym]>=h[x])
        {
            ans=max(ans,f[y][k].second);
            if (them2==0) them2+=kq[y];
            y=ym;
        }
    }

    for (ll k=19;k>=0;k--)
        if (f[x][k].first!=f[y][k].first)
        {
            ans=max(ans,max(f[x][k].second,f[y][k].second));
            x=f[x][k].first; y=f[y][k].first;
        }

    while (x!=y)
    {
        ans=max(ans,max(f[x][0].second,f[y][0].second));
        x=f[x][0].first; y=f[y][0].first;
    }
    //cout<<ans<<" "<<them1<<" "<<them2<<'\n';
    return ans;//+them1+them2;
}
int main()
{
    cin>>n>>m>>k>>test;
    for (ll i=1;i<=m;i++)
    {
        ll u,v,w; cin>>u>>v>>w;
        vt[u].emplace_back(v,w); vt[v].emplace_back(u,w);
    }

    for (ll i=1;i<=k;i++)
    {
        d[i]=0; g[i]=i;
        q.emplace(0,i);
    }
    for (ll i=k+1;i<=n;i++) d[i]=1e9+1;

    while (!q.empty())
    {
        ll u=q.top().second; q.pop();
        for (ll e=0;e<(ll)vt[u].size();e++)
        {
            ll v=vt[u][e].first; ll w=vt[u][e].second;
            if (d[v]>d[u]+w)
            {
                d[v]=d[u]+w;
                g[v]=g[u];
                q.emplace(d[v],v);
                if (g[u]==1) kq[1]=max(kq[1],d[v]);
            }
        }
    }

    //for (ll i=1;i<=n;i++) cout<<d[i]<<" "<<g[i]<<'\n';
    vector<node> canh;
    for (ll i=1;i<=n;i++)
    {
        for (ll e=0;e<(ll)vt[i].size();e++)
        {
            ll v=vt[i][e].first; ll w=vt[i][e].second;
            if (g[i]==g[v]) continue;
            canh.push_back(node(i,v,w+d[i]+d[v]));
        }
        vt[i].clear();
    }

    sort(canh.begin(),canh.end(),cmp);
    for (ll i=1;i<=k;i++) p[i]=i;

    for (ll i=0;i<(ll)canh.size();i++)
    {
        ll u=g[canh[i].u]; ll v=g[canh[i].v]; ll w=canh[i].w;
        if (unite(u,v))
        {
            vt[u].emplace_back(v,w);
            vt[v].emplace_back(u,w);
            vt1[u].emplace_back(d[canh[i].u],d[canh[i].v]);
            vt1[v].emplace_back(d[canh[i].v],d[canh[i].u]);
        }
    }

    f[1][0]={-1,0};
    dfs(1,-1);
    for (ll j=1;j<=20;j++)
        for (ll i=1;i<=k;i++)
        {
            f[i][j].first=f[f[i][j-1].first][j-1].first;
            f[i][j].second=max(f[i][j-1].second,f[f[i][j-1].first][j-1].second);
        }

    //for (ll i=1;i<=k;i++) cout<<kq[i]<<'\n';
    while (test--)
    {
        ll x,y; cin>>x>>y;
        cout<<tv(x,y)<<'\n';//+kq[x]+kq[y]<<'\n';
    }
    return 0;
}


#include <bits/stdc++.h>
#define ll long long
#define nmax 200010

using namespace std;
struct node
{
    int u,v; ll w;
    node() {u=v=w=0;}
    node(ll x,ll y,ll z) {u=x;v=y;w=z;}
};
bool cmp(const node &a,const node &b)
{
    return (a.w<b.w);
}
int n,m,k,test,g[nmax],p[nmax],lab[nmax],h[nmax];
ll d[nmax];
pair<int,ll> f[nmax][30];
vector<pair<int,ll> > vt[nmax];
vector<pair<int,ll> > vt1[nmax];
priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > > q;
ll find(ll r)
{
    if (r!=p[r]) return p[r]=find(p[r]);
    return p[r];
}
bool unite(ll x,ll y)
{
    x=find(x); y=find(y);
    if (x==y) return 0;
    if (lab[x]==lab[y]) lab[x]++;

    if (lab[x]<lab[y]) p[x]=y;
    else p[y]=x;
    return 1;
}
void dfs(int u,int cha)
{
    for (int e=0;e<(ll)vt[u].size();e++)
    {
        int v=vt[u][e].first; ll w=vt[u][e].second;
        if (v==cha) continue;
        h[v]=h[u]+1; f[v][0]={u,w};
        dfs(v,u);
    }
}
ll tv(int x,int y)
{
    ll ans=0;
    for (int k=19;k>=0;k--)
    {
        int xm=f[x][k].first;
        if (h[xm]>=h[y])
        {
            ans=max(ans,f[x][k].second);
            x=xm;
        }
    }
    for (int k=19;k>=0;k--)
    {
        int ym=f[y][k].first;
        if (h[ym]>=h[x])
        {
            ans=max(ans,f[y][k].second);
            y=ym;
        }
    }

    for (int k=19;k>=0;k--)
        if (f[x][k].first!=f[y][k].first)
        {
            ans=max(ans,max(f[x][k].second,f[y][k].second));
            x=f[x][k].first; y=f[y][k].first;
        }

    while (x!=y)
    {
        ans=max(ans,max(f[x][0].second,f[y][0].second));
        x=f[x][0].first; y=f[y][0].first;
    }
    //cout<<ans<<" "<<them1<<" "<<them2<<'\n';
    return ans;//+them1+them2;
}
int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin>>n>>m>>k>>test;
    for (int i=1;i<=m;i++)
    {
        int u,v; ll w; cin>>u>>v>>w;
        vt[u].emplace_back(v,w); vt[v].emplace_back(u,w);
    }

    for (int i=1;i<=k;i++)
    {
        d[i]=0; g[i]=i;
        q.emplace(0,i);
    }
    for (int i=k+1;i<=n;i++) d[i]=1e18;

    while (!q.empty())
    {
        int u=q.top().second; q.pop();
        for (int e=0;e<(int)vt[u].size();e++)
        {
            int v=vt[u][e].first; ll w=vt[u][e].second;
            if (d[v]>d[u]+w)
            {
                d[v]=d[u]+w;
                g[v]=g[u];
                q.emplace(d[v],v);
            }
        }
    }

    //for (ll i=1;i<=n;i++) cout<<d[i]<<" "<<g[i]<<'\n';
    vector<node> canh;
    for (int i=1;i<=n;i++)
    {
        for (int e=0;e<(ll)vt[i].size();e++)
        {
            int v=vt[i][e].first; ll w=vt[i][e].second;
            if (g[i]==g[v]) continue;
            canh.push_back(node(i,v,w+d[i]+d[v]));
        }
        vt[i].clear();
    }

    sort(canh.begin(),canh.end(),cmp);
    for (int i=1;i<=k;i++) p[i]=i;

    for (int i=0;i<(int)canh.size();i++)
    {
        int u=g[canh[i].u]; int v=g[canh[i].v]; ll w=canh[i].w;
        if (unite(u,v))
        {
            vt[u].emplace_back(v,w);
            vt[v].emplace_back(u,w);
            vt1[u].emplace_back(d[canh[i].u],d[canh[i].v]);
            vt1[v].emplace_back(d[canh[i].v],d[canh[i].u]);
        }
    }

    f[1][0]={-1,0};
    dfs(1,-1);
    for (int j=1;j<=20;j++)
        for (int i=1;i<=k;i++)
        {
            f[i][j].first=f[f[i][j-1].first][j-1].first;
            f[i][j].second=max(f[i][j-1].second,f[f[i][j-1].first][j-1].second);
        }

    //for (ll i=1;i<=k;i++) cout<<kq[i]<<'\n';
    while (test--)
    {
        int x,y; cin>>x>>y;
        cout<<tv(x,y)<<'\n';//+kq[x]+kq[y]<<'\n';
    }
    return 0;
}


#include <bits/stdc++.h>
#define ll long long
#define nmax 310

using namespace std;
struct node
{
    ll u,v,w;
    node() {u=v=w=0;}
    node(ll x,ll y,ll z) {u=x;v=y;w=z;}
};
bool cmp(const node &a,const node &b)
{
    return (a.w<b.w);
}
ll n,m,k,test,d[nmax],g[nmax],p[nmax],lab[nmax],h[nmax],kq[nmax];
pair<ll,ll> f[nmax][30];
vector<pair<ll,ll> > vt[nmax];
vector<pair<ll,ll> > vt1[nmax];
priority_queue<pair<ll,ll>,vector<pair<ll,ll> >,greater<pair<ll,ll> > > q;
ll find(ll r)
{
    if (r!=p[r]) return p[r]=find(p[r]);
    return p[r];
}
bool unite(ll x,ll y)
{
    x=find(x); y=find(y);
    if (x==y) return 0;
    if (lab[x]==lab[y]) lab[x]++;

    if (lab[x]<lab[y]) p[x]=y;
    else p[y]=x;
    return 1;
}
void dfs(ll u,ll cha)
{
    for (ll e=0;e<(ll)vt[u].size();e++)
    {
        ll v=vt[u][e].first; ll w=vt[u][e].second;
        if (v==cha) continue;
        h[v]=h[u]+1; f[v][0]={u,w}; kq[v]=vt1[u][e].second;
        dfs(v,u);
    }
}
ll tv(ll x,ll y)
{
    ll ans=0; ll them1=0,them2=0;
    for (ll k=19;k>=0;k--)
    {
        ll xm=f[x][k].first;
        if (h[xm]>=h[y])
        {
            ans=max(ans,f[x][k].second);
            if (them1==0) them1+=kq[x];
            x=xm;
        }
    }
    for (ll k=19;k>=0;k--)
    {
        ll ym=f[y][k].first;
        if (h[ym]>=h[x])
        {
            ans=max(ans,f[y][k].second);
            if (them2==0) them2+=kq[y];
            y=ym;
        }
    }

    for (ll k=19;k>=0;k--)
        if (f[x][k].first!=f[y][k].first)
        {
            ans=max(ans,max(f[x][k].second,f[y][k].second));
            x=f[x][k].first; y=f[y][k].first;
        }

    while (x!=y)
    {
        ans=max(ans,max(f[x][0].second,f[y][0].second));
        x=f[x][0].first; y=f[y][0].first;
    }
    //cout<<ans<<" "<<them1<<" "<<them2<<'\n';
    return ans;//+them1+them2;
}
int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin>>n>>m>>k>>test;
    for (ll i=1;i<=m;i++)
    {
        ll u,v,w; cin>>u>>v>>w;
        vt[u].emplace_back(v,w); vt[v].emplace_back(u,w);
    }

    for (ll i=1;i<=k;i++)
    {
        d[i]=0; g[i]=i;
        q.emplace(0,i);
    }
    for (ll i=k+1;i<=n;i++) d[i]=1e18;

    while (!q.empty())
    {
        ll u=q.top().second; q.pop();
        for (ll e=0;e<(ll)vt[u].size();e++)
        {
            ll v=vt[u][e].first; ll w=vt[u][e].second;
            if (d[v]>d[u]+w)
            {
                d[v]=d[u]+w;
                g[v]=g[u];
                q.emplace(d[v],v);
                if (g[u]==1) kq[1]=max(kq[1],d[v]);
            }
        }
    }

    //for (ll i=1;i<=n;i++) cout<<d[i]<<" "<<g[i]<<'\n';
    vector<node> canh;
    for (ll i=1;i<=n;i++)
    {
        for (ll e=0;e<(ll)vt[i].size();e++)
        {
            ll v=vt[i][e].first; ll w=vt[i][e].second;
            if (g[i]==g[v]) continue;
            canh.push_back(node(i,v,w+d[i]+d[v]));
        }
        vt[i].clear();
    }

    sort(canh.begin(),canh.end(),cmp);
    for (ll i=1;i<=k;i++) p[i]=i;

    for (ll i=0;i<(ll)canh.size();i++)
    {
        ll u=g[canh[i].u]; ll v=g[canh[i].v]; ll w=canh[i].w;
        if (unite(u,v))
        {
            vt[u].emplace_back(v,w);
            vt[v].emplace_back(u,w);
            vt1[u].emplace_back(d[canh[i].u],d[canh[i].v]);
            vt1[v].emplace_back(d[canh[i].v],d[canh[i].u]);
        }
    }

    f[1][0]={-1,0};
    dfs(1,-1);
    for (ll j=1;j<=20;j++)
        for (ll i=1;i<=k;i++)
        {
            f[i][j].first=f[f[i][j-1].first][j-1].first;
            f[i][j].second=max(f[i][j-1].second,f[f[i][j-1].first][j-1].second);
        }

    //for (ll i=1;i<=k;i++) cout<<kq[i]<<'\n';
    while (test--)
    {
        ll x,y; cin>>x>>y;
        cout<<tv(x,y)<<'\n';//+kq[x]+kq[y]<<'\n';
    }
    return 0;
}


#include <bits/stdc++.h>
#define ll long long
#define nmax 200010

using namespace std;
struct node
{
    ll u,v,w;
    node() {u=v=w=0;}
    node(ll x,ll y,ll z) {u=x;v=y;w=z;}
};
bool cmp(const node &a,const node &b)
{
    return (a.w<b.w);
}
ll n,m,k,test,d[nmax],g[nmax],p[nmax],lab[nmax],h[nmax],kq[nmax];
pair<ll,ll> f[nmax][30];
vector<pair<ll,ll> > vt[nmax];
vector<pair<ll,ll> > vt1[nmax];
priority_queue<pair<ll,ll>,vector<pair<ll,ll> >,greater<pair<ll,ll> > > q;
ll find(ll r)
{
    if (r!=p[r]) return p[r]=find(p[r]);
    return p[r];
}
bool unite(ll x,ll y)
{
    x=find(x); y=find(y);
    if (x==y) return 0;
    if (lab[x]==lab[y]) lab[x]++;

    if (lab[x]<lab[y]) p[x]=y;
    else p[y]=x;
    return 1;
}
void dfs(ll u,ll cha)
{
    for (ll e=0;e<(ll)vt[u].size();e++)
    {
        ll v=vt[u][e].first; ll w=vt[u][e].second;
        if (v==cha) continue;
        h[v]=h[u]+1; f[v][0]={u,w}; kq[v]=vt1[u][e].second;
        dfs(v,u);
    }
}
ll tv(ll x,ll y)
{
    ll ans=0; ll them1=0,them2=0;
    for (ll k=19;k>=0;k--)
    {
        ll xm=f[x][k].first;
        if (h[xm]>=h[y])
        {
            ans=max(ans,f[x][k].second);
            if (them1==0) them1+=kq[x];
            x=xm;
        }
    }
    for (ll k=19;k>=0;k--)
    {
        ll ym=f[y][k].first;
        if (h[ym]>=h[x])
        {
            ans=max(ans,f[y][k].second);
            if (them2==0) them2+=kq[y];
            y=ym;
        }
    }

    for (ll k=19;k>=0;k--)
        if (f[x][k].first!=f[y][k].first)
        {
            ans=max(ans,max(f[x][k].second,f[y][k].second));
            x=f[x][k].first; y=f[y][k].first;
        }

    while (x!=y)
    {
        ans=max(ans,max(f[x][0].second,f[y][0].second));
        x=f[x][0].first; y=f[y][0].first;
    }
    //cout<<ans<<" "<<them1<<" "<<them2<<'\n';
    return ans;//+them1+them2;
}
int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin>>n>>m>>k>>test;
    for (ll i=1;i<=m;i++)
    {
        ll u,v,w; cin>>u>>v>>w;
        vt[u].emplace_back(v,w); vt[v].emplace_back(u,w);
    }

    for (ll i=1;i<=k;i++)
    {
        d[i]=0; g[i]=i;
        q.emplace(0,i);
    }
    for (ll i=k+1;i<=n;i++) d[i]=1e18;

    while (!q.empty())
    {
        ll u=q.top().second; q.pop();
        for (ll e=0;e<(ll)vt[u].size();e++)
        {
            ll v=vt[u][e].first; ll w=vt[u][e].second;
            if (d[v]>d[u]+w)
            {
                d[v]=d[u]+w;
                g[v]=g[u];
                q.emplace(d[v],v);
                if (g[u]==1) kq[1]=max(kq[1],d[v]);
            }
        }
    }

    //for (ll i=1;i<=n;i++) cout<<d[i]<<" "<<g[i]<<'\n';
    vector<node> canh;
    for (ll i=1;i<=n;i++)
    {
        for (ll e=0;e<(ll)vt[i].size();e++)
        {
            ll v=vt[i][e].first; ll w=vt[i][e].second;
            if (g[i]==g[v]) continue;
            canh.push_back(node(i,v,w+d[i]+d[v]));
        }
        vt[i].clear();
    }

    sort(canh.begin(),canh.end(),cmp);
    for (ll i=1;i<=k;i++) p[i]=i;

    for (ll i=0;i<(ll)canh.size();i++)
    {
        ll u=g[canh[i].u]; ll v=g[canh[i].v]; ll w=canh[i].w;
        if (unite(u,v))
        {
            vt[u].emplace_back(v,w);
            vt[v].emplace_back(u,w);
            vt1[u].emplace_back(d[canh[i].u],d[canh[i].v]);
            vt1[v].emplace_back(d[canh[i].v],d[canh[i].u]);
        }
    }

    f[1][0]={-1,0};
    dfs(1,-1);
    for (ll j=1;j<=20;j++)
        for (ll i=1;i<=k;i++)
        {
            f[i][j].first=f[f[i][j-1].first][j-1].first;
            f[i][j].second=max(f[i][j-1].second,f[f[i][j-1].first][j-1].second);
        }

    //for (ll i=1;i<=k;i++) cout<<kq[i]<<'\n';
    while (test--)
    {
        ll x,y; cin>>x>>y;
        cout<<tv(x,y)<<'\n';//+kq[x]+kq[y]<<'\n';
    }
    return 0;
}


#include <bits/stdc++.h>
#define ll long long
#define nmax 200010

using namespace std;
struct node
{
    int u,v; ll w;
    node() {u=v=w=0;}
    node(ll x,ll y,ll z) {u=x;v=y;w=z;}
};
bool cmp(const node &a,const node &b)
{
    return (a.w<b.w);
}
int n,m,k,test,g[nmax],p[nmax],lab[nmax],h[nmax];
ll d[nmax];
bool trace[nmax];
pair<int,ll> f[nmax][30];
vector<pair<int,ll> > vt[nmax];
vector<pair<int,ll> > vt1[nmax];
priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > > q;
ll find(ll r)
{
    if (r!=p[r]) return p[r]=find(p[r]);
    return p[r];
}
bool unite(ll x,ll y)
{
    x=find(x); y=find(y);
    if (x==y) return 0;
    if (lab[x]==lab[y]) lab[x]++;

    if (lab[x]<lab[y]) p[x]=y;
    else p[y]=x;
    return 1;
}
void dfs(int u,int cha)
{
    for (int e=0;e<(int)vt1[u].size();e++)
    {
        int v=vt1[u][e].first; ll w=vt1[u][e].second;
        if (v==cha) continue;
        h[v]=h[u]+1; f[v][0]={u,w};
        dfs(v,u);
    }
}
ll tv(int x,int y)
{
    ll ans=0;
    for (int k=19;k>=0;k--)
    {
        int xm=f[x][k].first;
        if (h[xm]>=h[y])
        {
            ans=max(ans,f[x][k].second);
            x=xm;
        }
    }
    for (int k=19;k>=0;k--)
    {
        int ym=f[y][k].first;
        if (h[ym]>=h[x])
        {
            ans=max(ans,f[y][k].second);
            y=ym;
        }
    }

    for (int k=19;k>=0;k--)
        if (f[x][k].first!=f[y][k].first)
        {
            ans=max(ans,max(f[x][k].second,f[y][k].second));
            x=f[x][k].first; y=f[y][k].first;
        }

    while (x!=y)
    {
        ans=max(ans,max(f[x][0].second,f[y][0].second));
        x=f[x][0].first; y=f[y][0].first;
    }
    //cout<<ans<<" "<<them1<<" "<<them2<<'\n';
    return ans;//+them1+them2;
}
int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin>>n>>m>>k>>test;
    for (int i=1;i<=m;i++)
    {
        int u,v; ll w; cin>>u>>v>>w;
        vt[u].emplace_back(v,w); vt[v].emplace_back(u,w);
    }

    for (int i=1;i<=k;i++)
    {
        d[i]=0; g[i]=i;
        q.emplace(0,i);
    }
    for (int i=k+1;i<=n;i++) d[i]=1e18;

    while (!q.empty())
    {
        int u=q.top().second; q.pop();
        if (trace[u]==1) continue;
        trace[u]=1;
        for (int e=0;e<(int)vt[u].size();e++)
        {
            int v=vt[u][e].first; ll w=vt[u][e].second;
            if (d[v]>d[u]+w)
            {
                d[v]=d[u]+w;
                g[v]=g[u];
                q.emplace(d[v],v);
            }
        }
    }

    //for (ll i=1;i<=n;i++) cout<<d[i]<<" "<<g[i]<<'\n';
    vector<node> canh;
    for (int i=1;i<=n;i++)
    {
        for (int e=0;e<(int)vt[i].size();e++)
        {
            int v=vt[i][e].first; ll w=vt[i][e].second;
            if (g[i]==g[v]) continue;
            canh.push_back(node(i,v,w+d[i]+d[v]));
        }
        //vt[i].clear();
    }

    sort(canh.begin(),canh.end(),cmp);
    for (int i=1;i<=k;i++) p[i]=i;

    for (int i=0;i<(int)canh.size();i++)
    {
        int u=g[canh[i].u]; int v=g[canh[i].v]; ll w=canh[i].w;
        if (unite(u,v))
        {
            vt1[u].emplace_back(v,w);
            vt1[v].emplace_back(u,w);
        }
    }

    f[1][0]={-1,0};
    dfs(1,-1);
    for (int j=1;j<=20;j++)
        for (int i=1;i<=k;i++)
        {
            f[i][j].first=f[f[i][j-1].first][j-1].first;
            f[i][j].second=max(f[i][j-1].second,f[f[i][j-1].first][j-1].second);
        }

    //for (ll i=1;i<=k;i++) cout<<kq[i]<<'\n';
    while (test--)
    {
        int x,y; cin>>x>>y;
        cout<<tv(x,y)<<'\n';//+kq[x]+kq[y]<<'\n';
    }
    return 0;
}


#include <bits/stdc++.h>
#define ll long long
#define nmax 310

using namespace std;
struct node
{
    ll u,v,w;
    node() {u=v=w=0;}
    node(ll x,ll y,ll z) {u=x;v=y;w=z;}
};
bool cmp(const node &a,const node &b)
{
    return (a.w<b.w);
}
ll n,m,k,test,d[nmax],g[nmax],p[nmax],lab[nmax],h[nmax],kq[nmax];
pair<ll,ll> f[nmax][30];
vector<pair<ll,ll> > vt[nmax];
vector<pair<ll,ll> > vt1[nmax];
priority_queue<pair<ll,ll>,vector<pair<ll,ll> >,greater<pair<ll,ll> > > q;
ll find(ll r)
{
    if (r!=p[r]) return p[r]=find(p[r]);
    return p[r];
}
bool unite(ll x,ll y)
{
    x=find(x); y=find(y);
    if (x==y) return 0;
    if (lab[x]==lab[y]) lab[x]++;

    if (lab[x]<lab[y]) p[x]=y;
    else p[y]=x;
    return 1;
}
void dfs(ll u,ll cha)
{
    for (ll e=0;e<(ll)vt[u].size();e++)
    {
        ll v=vt[u][e].first; ll w=vt[u][e].second;
        if (v==cha) continue;
        h[v]=h[u]+1; f[v][0]={u,w}; kq[v]=vt1[u][e].second;
        dfs(v,u);
    }
}
ll tv(ll x,ll y)
{
    ll ans=0; ll them1=0,them2=0;
    for (ll k=19;k>=0;k--)
    {
        ll xm=f[x][k].first;
        if (h[xm]>=h[y])
        {
            ans=max(ans,f[x][k].second);
            if (them1==0) them1+=kq[x];
            x=xm;
        }
    }
    for (ll k=19;k>=0;k--)
    {
        ll ym=f[y][k].first;
        if (h[ym]>=h[x])
        {
            ans=max(ans,f[y][k].second);
            if (them2==0) them2+=kq[y];
            y=ym;
        }
    }

    for (ll k=19;k>=0;k--)
        if (f[x][k].first!=f[y][k].first)
        {
            ans=max(ans,max(f[x][k].second,f[y][k].second));
            x=f[x][k].first; y=f[y][k].first;
        }

    while (x!=y)
    {
        ans=max(ans,max(f[x][0].second,f[y][0].second));
        x=f[x][0].first; y=f[y][0].first;
    }
    //cout<<ans<<" "<<them1<<" "<<them2<<'\n';
    return ans;//+them1+them2;
}
int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin>>n>>m>>k>>test;
    for (ll i=1;i<=m;i++)
    {
        ll u,v,w; cin>>u>>v>>w;
        vt[u].emplace_back(v,w); vt[v].emplace_back(u,w);
    }

    for (ll i=1;i<=k;i++)
    {
        d[i]=0; g[i]=i;
        q.emplace(0,i);
    }
    for (ll i=k+1;i<=n;i++) d[i]=1e9+1;

    while (!q.empty())
    {
        ll u=q.top().second; q.pop();
        for (ll e=0;e<(ll)vt[u].size();e++)
        {
            ll v=vt[u][e].first; ll w=vt[u][e].second;
            if (d[v]>d[u]+w)
            {
                d[v]=d[u]+w;
                g[v]=g[u];
                q.emplace(d[v],v);
                if (g[u]==1) kq[1]=max(kq[1],d[v]);
            }
        }
    }

    //for (ll i=1;i<=n;i++) cout<<d[i]<<" "<<g[i]<<'\n';
    vector<node> canh;
    for (ll i=1;i<=n;i++)
    {
        for (ll e=0;e<(ll)vt[i].size();e++)
        {
            ll v=vt[i][e].first; ll w=vt[i][e].second;
            if (g[i]==g[v]) continue;
            canh.push_back(node(i,v,w+d[i]+d[v]));
        }
        vt[i].clear();
    }

    sort(canh.begin(),canh.end(),cmp);
    for (ll i=1;i<=k;i++) p[i]=i;

    for (ll i=0;i<(ll)canh.size();i++)
    {
        ll u=g[canh[i].u]; ll v=g[canh[i].v]; ll w=canh[i].w;
        if (unite(u,v))
        {
            vt[u].emplace_back(v,w);
            vt[v].emplace_back(u,w);
            vt1[u].emplace_back(d[canh[i].u],d[canh[i].v]);
            vt1[v].emplace_back(d[canh[i].v],d[canh[i].u]);
        }
    }

    f[1][0]={-1,0};
    dfs(1,-1);
    for (ll j=1;j<=20;j++)
        for (ll i=1;i<=k;i++)
        {
            f[i][j].first=f[f[i][j-1].first][j-1].first;
            f[i][j].second=max(f[i][j-1].second,f[f[i][j-1].first][j-1].second);
        }

    //for (ll i=1;i<=k;i++) cout<<kq[i]<<'\n';
    while (test--)
    {
        ll x,y; cin>>x>>y;
        cout<<tv(x,y)<<'\n';//+kq[x]+kq[y]<<'\n';
    }
    return 0;
}


#include<bits/stdc++.h>
//{ PXH612
using namespace std;
#define ll long long
#define db double
#define pi pair<int,int>
#define x first
#define y second

template<typename A,typename B>bool Min(A &a,B b){if(a<=b) return 0;a=b;return 1;}
template<typename A,typename B>bool Max(A &a,B b){if(a>=b) return 0;a=b;return 1;}
#define in ({ll x=0;int o=0,c=char(),t=0;for(;!isdigit(c)&&t<1000;c=getchar(),t++) o=c=='-';for(;isdigit(c);c=getchar()) x=x*10+c-'0';o?-x:x;})
#define inchar ({char c=getchar();while(c==' '||c=='\n') c=getchar();return c;})

#define FOR(i,a,b) for(int i=a,_=b;i<=_;i++)
#define ROF(i,a,b) for(int i=b,_=a;_<=i;i--)
#define RR(x,a,b) {cout<<#x<<": ";FOR(__,a,b) cout<<x[__]<<" ";cout<<"\n";}
#define rr(x) " "<<#x<<'='<<(x)<<" "

#define VEC(i,a) for(auto&i:a)
#define pb push_back
#define fiv(a) (int)a.size()-1
#define vl(v,x) (upper_bound(v.begin(),v.end(),x)-v.begin()-1)
#define vr(v,x) (lower_bound(v.begin(),v.end(),x)-v.begin())

#define bit(x,i) ((x>>(i-1))&1ll)
#define on(x,i) (x|(1ll<<(i-1)))
#define off(x,i) (x&~(1ll<<(i-1)))
#define mu2(x) (1ll<<x)
#define bitnum(x) __builtin_popcountll(x)

#define STDIN(a) freopen(a,"r",stdin);
#define STDOUT(b) freopen(b,"w",stdout);
#define MID(a,b) (a+(b-(a))/2)
#define MEMSET(x,a) memset(x,a,sizeof x)
//}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

const int N=3e5+5;
int n,m,k,q;
vector<pi> e[N];

#define tp tuple<ll,int,int>
#define mt make_tuple
vector<tp> ed;
priority_queue<tp,vector<tp>,greater<tp>> h;

ll f[N];
int g[N];
void ADD(ll len,int x,int z)
{
    if(g[x]&&g[x]!=z) ed.pb(mt(f[x]+len,g[x],z));
    if(Min(f[x],len))
    {
        g[x]=z;
        h.push(mt(len,x,z));
    }
}
void DIJ()
{
    FOR(i,1,k) ADD(0,i,i);
    while(h.size())
    {
        ll len,x,f;
        tie(len,x,f)=h.top();h.pop();

        VEC(i,e[x]) ADD(len+i.y,i.x,f);
    }
}

set<int> s[N];
ll ans[N];

int dsu[N];
int r(int x){return dsu[x]==0?x:dsu[x]=r(dsu[x]);}
void JOIN(int x,int y,ll len)
{
    if((x=r(x))==(y=r(y))) return ;
    if(s[x].size()<s[y].size()) swap(x,y);

    vector<int> v;
    VEC(i,s[y]) if(s[x].count(i))
    {
        ans[i]=len;
        v.pb(i);
    }
    VEC(i,s[y]) s[x].insert(i);s[y].clear();
    VEC(i,v) s[x].erase(i);

    dsu[y]=x;
}
main()
{
   // STDIN("F.inp");
    n=in,m=in,k=in,q=in;
    MEMSET(f,127);
    FOR(i,1,m)
    {
        int x=in,y=in,z=in;
        e[x].pb({y,z});
        e[y].pb({x,z});
    }
    DIJ();
    FOR(i,1,q)
    {
        int x=in,y=in;
        s[x].insert(i);
        s[y].insert(i);
    }
    sort(ed.begin(),ed.end());
    VEC(i,ed)
    {
        ll len,x,f;tie(len,x,f)=i;
        JOIN(x,f,len);
    }
    FOR(i,1,q) cout<<ans[i]<<"\n";
}


#include<bits/stdc++.h>
#define int long long
//{ PXH612
using namespace std;
#define ll long long
#define db double
#define pi pair<int,int>
#define x first
#define y second

template<typename A,typename B>bool Min(A &a,B b){if(a<=b) return 0;a=b;return 1;}
template<typename A,typename B>bool Max(A &a,B b){if(a>=b) return 0;a=b;return 1;}
#define in ({ll x=0;int o=0,c=char(),t=0;for(;!isdigit(c)&&t<1000;c=getchar(),t++) o=c=='-';for(;isdigit(c);c=getchar()) x=x*10+c-'0';o?-x:x;})
#define inchar ({char c=getchar();while(c==' '||c=='\n') c=getchar();return c;})

#define FOR(i,a,b) for(int i=a,_=b;i<=_;i++)
#define ROF(i,a,b) for(int i=b,_=a;_<=i;i--)
#define RR(x,a,b) {cout<<#x<<": ";FOR(__,a,b) cout<<x[__]<<" ";cout<<"\n";}
#define rr(x) " "<<#x<<'='<<(x)<<" "

#define VEC(i,a) for(auto&i:a)
#define pb push_back
#define fiv(a) (int)a.size()-1
#define vl(v,x) (upper_bound(v.begin(),v.end(),x)-v.begin()-1)
#define vr(v,x) (lower_bound(v.begin(),v.end(),x)-v.begin())

#define bit(x,i) ((x>>(i-1))&1ll)
#define on(x,i) (x|(1ll<<(i-1)))
#define off(x,i) (x&~(1ll<<(i-1)))
#define mu2(x) (1ll<<x)
#define bitnum(x) __builtin_popcountll(x)

#define STDIN(a) freopen(a,"r",stdin);
#define STDOUT(b) freopen(b,"w",stdout);
#define MID(a,b) (a+(b-(a))/2)
#define MEMSET(x,a) memset(x,a,sizeof x)
//}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

const int N=3e5+5;
int n,m,k,q;
vector<pi> e[N];

#define tp tuple<ll,int,int>
#define mt make_tuple
vector<tp> ed;
priority_queue<tp,vector<tp>,greater<tp>> h;

ll f[N];
int g[N];
void ADD(int len,int x,int z)
{
    if(g[x]&&g[x]!=z) ed.pb(mt(f[x]+len,g[x],z));
    if(Min(f[x],len))
    {
        g[x]=z;
        h.push(mt(len,x,z));
    }
}
void DIJ()
{
    FOR(i,1,k) ADD(0,i,i);
    while(h.size())
    {
        int len,x,f;
        tie(len,x,f)=h.top();h.pop();

        VEC(i,e[x]) ADD(len+i.y,i.x,f);
    }
}

set<int> s[N];
ll ans[N];

int dsu[N];
int r(int x){return dsu[x]==0?x:dsu[x]=r(dsu[x]);}
void JOIN(int x,int y,ll len)
{
    if((x=r(x))==(y=r(y))) return ;
    if(s[x].size()>s[y].size()) swap(x,y);

    vector<int> v;
    VEC(i,s[x]) if(s[y].count(i))
    {
        ans[i]=len;
        v.pb(i);
    }
    VEC(i,s[y]) s[x].insert(i);s[y].clear();
    VEC(i,v) s[x].erase(i);

    dsu[y]=x;
}
main()
{
   // STDIN("F.inp");
    n=in,m=in,k=in,q=in;
    MEMSET(f,127);
    FOR(i,1,m)
    {
        int x=in,y=in,z=in;
        e[x].pb({y,z});
        e[y].pb({x,z});
    }
    DIJ();
    FOR(i,1,q)
    {
        int x=in,y=in;
        s[x].insert(i);
        s[y].insert(i);
    }
    sort(ed.begin(),ed.end());
    VEC(i,ed)
    {
        int len,x,f;tie(len,x,f)=i;
        JOIN(x,f,len);
    }
    FOR(i,1,q) cout<<ans[i]<<"\n";
}


#include<bits/stdc++.h>
//{ PXH612
using namespace std;
#define ll long long
#define db double
#define pi pair<int,int>
#define x first
#define y second

template<typename A,typename B>bool Min(A &a,B b){if(a<=b) return 0;a=b;return 1;}
template<typename A,typename B>bool Max(A &a,B b){if(a>=b) return 0;a=b;return 1;}
#define in ({ll x=0;int o=0,c=char(),t=0;for(;!isdigit(c)&&t<1000;c=getchar(),t++) o=c=='-';for(;isdigit(c);c=getchar()) x=x*10+c-'0';o?-x:x;})
#define inchar ({char c=getchar();while(c==' '||c=='\n') c=getchar();return c;})

#define FOR(i,a,b) for(int i=a,_=b;i<=_;i++)
#define ROF(i,a,b) for(int i=b,_=a;_<=i;i--)
#define RR(x,a,b) {cout<<#x<<": ";FOR(__,a,b) cout<<x[__]<<" ";cout<<"\n";}
#define rr(x) " "<<#x<<'='<<(x)<<" "

#define VEC(i,a) for(auto&i:a)
#define pb push_back
#define fiv(a) (int)a.size()-1
#define vl(v,x) (upper_bound(v.begin(),v.end(),x)-v.begin()-1)
#define vr(v,x) (lower_bound(v.begin(),v.end(),x)-v.begin())

#define bit(x,i) ((x>>(i-1))&1ll)
#define on(x,i) (x|(1ll<<(i-1)))
#define off(x,i) (x&~(1ll<<(i-1)))
#define mu2(x) (1ll<<x)
#define bitnum(x) __builtin_popcountll(x)

#define STDIN(a) freopen(a,"r",stdin);
#define STDOUT(b) freopen(b,"w",stdout);
#define MID(a,b) (a+(b-(a))/2)
#define MEMSET(x,a) memset(x,a,sizeof x)
//}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

const int N=3e5+5;
int n,m,k,q;
vector<pi> e[N];

#define tp tuple<ll,int,int>
#define mt make_tuple
vector<tp> ed;
priority_queue<tp,vector<tp>,greater<tp>> h;

ll f[N];
int g[N];
void ADD(ll len,int x,int z)
{
    if(g[x]&&g[x]!=z) ed.pb(mt(f[x]+len,g[x],z));
    if(Min(f[x],len))
    {
        g[x]=z;
        h.push(mt(len,x,z));
    }
}
void DIJ()
{
    FOR(i,1,k) ADD(0,i,i);
    while(h.size())
    {
        ll len,x,f;
        tie(len,x,f)=h.top();h.pop();

        VEC(i,e[x]) ADD(len+i.y,i.x,f);
    }
}

set<int> s[N];
ll ans[N];

int dsu[N];
int r(int x){return dsu[x]==0?x:dsu[x]=r(dsu[x]);}
void JOIN(int x,int y,ll len)
{
    if((x=r(x))==(y=r(y))) return ;
    if(s[x].size()>s[y].size()) swap(x,y);

    vector<int> v;
    VEC(i,s[x]) if(s[y].count(i))
    {
        ans[i]=len;
        v.pb(i);
    }
    VEC(i,s[y]) s[x].insert(i);s[y].clear();
    VEC(i,v) s[x].erase(i);

    dsu[y]=x;
}
main()
{
   // STDIN("F.inp");
    n=in,m=in,k=in,q=in;
    MEMSET(f,127);
    FOR(i,1,m)
    {
        int x=in,y=in,z=in;
        e[x].pb({y,z});
        e[y].pb({x,z});
    }
    DIJ();
    FOR(i,1,q)
    {
        int x=in,y=in;
        s[x].insert(i);
        s[y].insert(i);
    }
    sort(ed.begin(),ed.end());
    VEC(i,ed)
    {
        ll len,x,f;tie(len,x,f)=i;
        JOIN(x,f,len);
    }
    FOR(i,1,q) cout<<ans[i]<<"\n";
}


#include <bits/stdc++.h>

using namespace std;
typedef long long llint;

const int maxn = 1e5+10;
const llint inf = 1LL << 60;

const int logo = 20;
const int off = 1 << logo;
const int treesiz = off << 1;

int n, m, k, q;
vector< pair<int, llint> > graph[maxn];
vector< pair< llint, pair<int, int> > > v, vv;
int parr[maxn];
llint dis[maxn];
set< pair<llint, int> > s;
vector< pair< int, llint> > graph2[maxn];
int dub[maxn];
int dp[logo + 10][maxn];
llint sol[logo + 10][maxn];
bool bio[maxn];

int fin(int x) {
    if (x == parr[x]) return x;
    else return parr[x] = fin(parr[x]);
}

void merg(int a, int b) {
    a = fin(a);
    b = fin(b);
    if (a == b) return;

    int ra = rand() % 2;
    if (ra == 0) parr[a] = b;
    else parr[b] = a;
}

void dfs(int x, int parr, llint dist, int du) {
    dp[0][x] = parr;
    sol[0][x] = dist;
    dub[x] = du;
    bio[x] = true;

    for (int i = 0; i < graph2[x].size(); i++) {
        int tren = graph2[x][i].first;
        llint cost = graph2[x][i].second;

        if (bio[tren]) continue;
        dfs(tren, x, cost, du + 1);
    }
}

int lift(int x, int val) {
    for (int i = 0; i <= logo; i++)
        if (val & (1 << i)) x = dp[i][x];
    return x;
}

int lca(int x, int y) {
    if (dub[x] > dub[y]) x = lift(x, dub[x] - dub[y]);
    if (dub[y] > dub[x]) y = lift(y, dub[y] - dub[x]);
    if (x == y) return x;

    for (int i = logo; i >= 0; i--) {
        if (dp[i][x] != dp[i][y]) {
            x = dp[i][x];
            y = dp[i][y];
        }
    }
    return dp[0][x];
}

llint cal(int x, int val) {
    llint out = -inf;
    for (int i = 0; i <= logo; i++) {
        if (val & (1 << i)) {
            out = max(out, sol[i][x]);
            x = dp[i][x];
        }
    }
    return out;
}

int main() {
    srand(time(0));
    scanf("%d%d%d%d", &n, &m, &k, &q);
    for (int i = 0; i < m; i++) {
        int a, b;
        llint c;
        scanf("%d%d%lld", &a, &b, &c);

        graph[a].push_back(make_pair(b, c));
        graph[b].push_back(make_pair(a, c));
        v.push_back(make_pair(c, make_pair(a, b)));
    }

    for (int i = 1; i <= n; i++) dis[i] = inf;
    for (int i = 1; i <= k; i++) {
        dis[i] = 0;
        s.insert(make_pair(0, i));
    }

    while (!s.empty()) {
        llint dist = s.begin()->first;
        int x = s.begin()->second;
        s.erase(s.begin());

        for (int i = 0; i < graph[x].size(); i++) {
            int tren = graph[x][i].first;
            llint cost = graph[x][i].second;

            if (dis[tren] > dist + cost) {
                s.erase(make_pair(dis[tren], tren));
                dis[tren] = dist + cost;
                s.insert(make_pair(dis[tren], tren));
            }
        }
    }

    for (int i = 0; i < m; i++) {
        int a = v[i].second.first;
        int b = v[i].second.second;
        llint ac = v[i].first;

        ac += dis[a] + dis[b];
        vv.push_back(make_pair(ac, make_pair(a, b)));
    }

    sort(vv.begin(), vv.end());
    for (int i = 1; i <= n; i++) parr[i] = i;
    for (int i = 0; i < m; i++) {
        int x = vv[i].second.first;
        int y = vv[i].second.second;
        llint dist = vv[i].first;

        if (fin(x) != fin(y)) {
            graph2[x].push_back(make_pair(y, dist));
            graph2[y].push_back(make_pair(x, dist));
            merg(x, y);
        }
    }

    memset(bio, false, sizeof bio);
    dfs(1, 0, -inf, 1);
    for (int i = 1; i <= logo; i++) {
        for (int j = 1; j <= n; j++) {
            assert(dp[i - 1][j] >= 0);
            dp[i][j] = dp[i - 1][dp[i - 1][j]];
            sol[i][j] = max(sol[i - 1][j], sol[i - 1][dp[i - 1][j]]);
        }
    }

    for (int i = 0; i < q; i++) {
        int a, b;
        scanf("%d%d", &a, &b);

        int lc = lca(a, b);
        llint sol = max(cal(a, dub[a] - dub[lc]), cal(b, dub[b] - dub[lc]));
        printf("%lld\n", sol);
    }
    return 0;
}


#include <bits/stdc++.h>

using namespace std;
typedef long long llint;

const int maxn = 1e5+10;
const llint inf = 1LL << 60;

const int logo = 20;
const int off = 1 << logo;
const int treesiz = off << 1;

int n, m, k, q;
vector< pair<int, llint> > graph[maxn];
vector< pair< llint, pair<int, int> > > v, vv;
int parr[maxn];
llint dis[maxn];
set< pair<llint, int> > s;
vector< pair< int, llint> > graph2[maxn];
int dub[maxn];
int dp[logo + 10][maxn];
llint sol[logo + 10][maxn];
bool bio[maxn];

int fin(int x) {
    if (x == parr[x]) return x;
    else return parr[x] = fin(parr[x]);
}

void merg(int a, int b) {
    a = fin(a);
    b = fin(b);
    if (a == b) return;

    int ra = rand() % 2;
    if (ra == 0) parr[a] = b;
    else parr[b] = a;
}

void dfs(int x, int parr, llint dist, int du) {
    dp[0][x] = parr;
    sol[0][x] = dist;
    dub[x] = du;
    bio[x] = true;

    for (int i = 0; i < graph2[x].size(); i++) {
        int tren = graph2[x][i].first;
        llint cost = graph2[x][i].second;

        if (bio[tren]) continue;
        dfs(tren, x, cost, du + 1);
    }
}

int lift(int x, int val) {
    for (int i = 0; i <= logo; i++)
        if (val & (1 << i)) x = dp[i][x];
    return x;
}

int lca(int x, int y) {
    if (dub[x] > dub[y]) x = lift(x, dub[x] - dub[y]);
    if (dub[y] > dub[x]) y = lift(y, dub[y] - dub[x]);
    if (x == y) return x;

    for (int i = logo; i >= 0; i--) {
        if (dp[i][x] != dp[i][y]) {
            x = dp[i][x];
            y = dp[i][x];
        }
    }
    return dp[0][x];
}

llint cal(int x, int val) {
    llint out = -inf;
    for (int i = 0; i <= logo; i++) {
        if (val & (1 << i)) {
            out = max(out, sol[i][x]);
            x = dp[i][x];
        }
    }
    return out;
}

int main() {
    srand(time(0));
    scanf("%d%d%d%d", &n, &m, &k, &q);
    for (int i = 0; i < m; i++) {
        int a, b;
        llint c;
        scanf("%d%d%lld", &a, &b, &c);

        graph[a].push_back(make_pair(b, c));
        graph[b].push_back(make_pair(a, c));
        v.push_back(make_pair(c, make_pair(a, b)));
    }

    for (int i = 1; i <= n; i++) dis[i] = inf;
    for (int i = 1; i <= k; i++) {
        dis[i] = 0;
        s.insert(make_pair(0, i));
    }

    while (!s.empty()) {
        llint dist = s.begin()->first;
        int x = s.begin()->second;
        s.erase(s.begin());

        for (int i = 0; i < graph[x].size(); i++) {
            int tren = graph[x][i].first;
            llint cost = graph[x][i].second;

            if (dis[tren] > dist + cost) {
                s.erase(make_pair(dis[tren], tren));
                dis[tren] = dist + cost;
                s.insert(make_pair(dis[tren], tren));
            }
        }
    }

    for (int i = 0; i < m; i++) {
        int a = v[i].second.first;
        int b = v[i].second.second;
        llint ac = v[i].first;

        ac += dis[a] + dis[b];
        vv.push_back(make_pair(ac, make_pair(a, b)));
    }

    sort(vv.begin(), vv.end());
    for (int i = 1; i <= n; i++) parr[i] = i;
    for (int i = 0; i < m; i++) {
        int x = vv[i].second.first;
        int y = vv[i].second.second;
        llint dist = vv[i].first;

        if (fin(x) != fin(y)) {
            graph2[x].push_back(make_pair(y, dist));
            graph2[y].push_back(make_pair(x, dist));
            merg(x, y);
        }
    }

    memset(bio, false, sizeof bio);
    dfs(1, maxn - 5, -inf, 1);
    for (int i = 1; i <= logo; i++) {
        for (int j = 1; j <= n; j++) {
            dp[i][j] = dp[i - 1][dp[i - 1][j]];
            sol[i][j] = max(sol[i - 1][j], sol[i - 1][dp[i - 1][j]]);
        }
    }

    for (int i = 0; i < q; i++) {
        int a, b;
        scanf("%d%d", &a, &b);

        int lc = lca(a, b);
        llint sol = max(cal(a, dub[a] - dub[lc]), cal(b, dub[b] - dub[lc]));
        printf("%lld\n", sol);
    }
    return 0;
}


#include <bits/stdc++.h>

using namespace std;
typedef long long llint;

const int maxn = 1e5+10;
const llint inf = 1LL << 60;

const int logo = 20;
const int off = 1 << logo;
const int treesiz = off << 1;

int n, m, k, q;
vector< pair<int, llint> > graph[maxn];
vector< pair< llint, pair<int, int> > > v, vv;
int parr[maxn];
llint dis[maxn];
set< pair<llint, int> > s;
vector< pair< int, llint> > graph2[maxn];
int dub[maxn];
int dp[logo + 10][maxn];
llint sol[logo + 10][maxn];
bool bio[maxn];

int fin(int x) {
    if (x == parr[x]) return x;
    else return parr[x] = fin(parr[x]);
}

void merg(int a, int b) {
    a = fin(a);
    b = fin(b);
    if (a == b) return;

    int ra = rand() % 2;
    if (ra == 0) parr[a] = b;
    else parr[b] = a;
}

void dfs(int x, int parr, llint dist, int du) {
    dp[0][x] = parr;
    sol[0][x] = dist;
    dub[x] = du;
    bio[x] = true;

    for (int i = 0; i < graph2[x].size(); i++) {
        int tren = graph2[x][i].first;
        llint cost = graph2[x][i].second;

        if (bio[tren]) continue;
        dfs(tren, x, cost, du + 1);
    }
}

int lift(int x, int val) {
    for (int i = 0; i <= logo; i++)
        if (val & (1 << i)) x = dp[i][x];
    return x;
}

int lca(int x, int y) {
    if (dub[x] > dub[y]) x = lift(x, dub[x] - dub[y]);
    if (dub[y] > dub[x]) y = lift(y, dub[y] - dub[x]);
    if (x == y) return x;

    for (int i = logo; i >= 0; i--) {
        if (dp[i][x] != dp[i][y]) {
            x = dp[i][x];
            y = dp[i][x];
        }
    }
    return dp[0][x];
}

llint cal(int x, int val) {
    llint out = -inf;
    for (int i = 0; i <= logo; i++) {
        if (val & (1 << i)) {
            out = max(out, sol[i][x]);
            x = dp[i][x];
        }
    }
    return out;
}

int main() {
    srand(time(0));
    scanf("%d%d%d%d", &n, &m, &k, &q);
    for (int i = 0; i < m; i++) {
        int a, b;
        llint c;
        scanf("%d%d%lld", &a, &b, &c);

        graph[a].push_back(make_pair(b, c));
        graph[b].push_back(make_pair(a, c));
        v.push_back(make_pair(c, make_pair(a, b)));
    }

    for (int i = 1; i <= n; i++) dis[i] = inf;
    for (int i = 1; i <= k; i++) {
        dis[i] = 0;
        s.insert(make_pair(0, i));
    }

    while (!s.empty()) {
        llint dist = s.begin()->first;
        int x = s.begin()->second;
        s.erase(s.begin());

        for (int i = 0; i < graph[x].size(); i++) {
            int tren = graph[x][i].first;
            llint cost = graph[x][i].second;

            if (dis[tren] > dist + cost) {
                s.erase(make_pair(dis[tren], tren));
                dis[tren] = dist + cost;
                s.insert(make_pair(dis[tren], tren));
            }
        }
    }

    for (int i = 0; i < m; i++) {
        int a = v[i].second.first;
        int b = v[i].second.second;
        llint ac = v[i].first;

        ac += dis[a] + dis[b];
        vv.push_back(make_pair(ac, make_pair(a, b)));
    }

    sort(vv.begin(), vv.end());
    for (int i = 1; i <= n; i++) parr[i] = i;
    for (int i = 0; i < m; i++) {
        int x = vv[i].second.first;
        int y = vv[i].second.second;
        llint dist = vv[i].first;

        if (fin(x) != fin(y)) {
            graph2[x].push_back(make_pair(y, dist));
            graph2[y].push_back(make_pair(x, dist));
            merg(x, y);
        }
    }

    memset(bio, false, sizeof bio);
    dfs(1, 0, -inf, 1);
    for (int i = 1; i <= logo; i++) {
        for (int j = 1; j <= n; j++) {
            dp[i][j] = dp[i - 1][dp[i - 1][j]];
            sol[i][j] = max(sol[i - 1][j], sol[i - 1][dp[i - 1][j]]);
        }
    }

    for (int i = 0; i < q; i++) {
        int a, b;
        scanf("%d%d", &a, &b);

        int lc = lca(a, b);
        llint sol = max(cal(a, dub[a] - dub[lc]), cal(b, dub[b] - dub[lc]));
        printf("%lld\n", sol);
    }
    return 0;
}


#include <bits/stdc++.h>

using namespace std;
typedef long long llint;

const int maxn = 1e5+10;
const llint inf = 1LL << 60;

const int logo = 20;
const int off = 1 << logo;
const int treesiz = off << 1;

int n, m, k, q;
vector< pair<int, llint> > graph[maxn];
vector< pair< llint, pair<int, int> > > v, vv;
int parr[maxn];
llint dis[maxn];
set< pair<llint, int> > s;
vector< pair< int, llint> > graph2[maxn];
int dub[maxn];
int dp[logo + 10][maxn];
llint sol[logo + 10][maxn];
bool bio[maxn];

int fin(int x) {
    if (x == parr[x]) return x;
    else return parr[x] = fin(parr[x]);
}

void merg(int a, int b) {
    a = fin(a);
    b = fin(b);
    if (a == b) return;

    int ra = rand() % 2;
    if (ra == 0) parr[a] = b;
    else parr[b] = a;
}

void dfs(int x, int parr, llint dist, int du) {
    dp[0][x] = parr;
    sol[0][x] = dist;
    dub[x] = du;
    bio[x] = true;

    for (int i = 0; i < graph2[x].size(); i++) {
        int tren = graph2[x][i].first;
        llint cost = graph2[x][i].second;

        if (bio[tren]) continue;
        dfs(tren, x, cost, du + 1);
    }
}

int lift(int x, int val) {
    for (int i = 0; i <= logo; i++)
        if (val & (1 << i)) x = dp[i][x];
    return x;
}

int lca(int x, int y) {
    if (dub[x] > dub[y]) x = lift(x, dub[x] - dub[y]);
    if (dub[y] > dub[x]) y = lift(y, dub[y] - dub[x]);
    if (x == y) return x;

    for (int i = logo; i >= 0; i--) {
        if (dp[i][x] != dp[i][y]) {
            x = dp[i][x];
            y = dp[i][x];
        }
    }
    return dp[0][x];
}

llint cal(int x, int val) {
    llint out = -inf;
    for (int i = 0; i <= logo; i++) {
        if (val & (1 << i)) {
            out = max(out, sol[i][x]);
            x = dp[i][x];
        }
    }
    return out;
}

int main() {
    srand(time(0));
    scanf("%d%d%d%d", &n, &m, &k, &q);
    for (int i = 0; i < m; i++) {
        int a, b;
        llint c;
        scanf("%d%d%lld", &a, &b, &c);

        graph[a].push_back(make_pair(b, c));
        graph[b].push_back(make_pair(a, c));
        v.push_back(make_pair(c, make_pair(a, b)));
    }

    for (int i = 1; i <= n; i++) dis[i] = inf;
    for (int i = 1; i <= k; i++) {
        dis[i] = 0;
        s.insert(make_pair(0, i));
    }

    while (!s.empty()) {
        llint dist = s.begin()->first;
        int x = s.begin()->second;
        s.erase(s.begin());

        for (int i = 0; i < graph[x].size(); i++) {
            int tren = graph[x][i].first;
            llint cost = graph[x][i].second;

            if (dis[tren] > dist + cost) {
                s.erase(make_pair(dis[tren], tren));
                dis[tren] = dist + cost;
                s.insert(make_pair(dis[tren], tren));
            }
        }
    }

    for (int i = 0; i < m; i++) {
        int a = v[i].second.first;
        int b = v[i].second.second;
        llint ac = v[i].first;

        ac += dis[a] + dis[b];
        vv.push_back(make_pair(ac, make_pair(a, b)));
    }

    sort(vv.begin(), vv.end());
    for (int i = 1; i <= n; i++) parr[i] = i;
    for (int i = 0; i < m; i++) {
        int x = vv[i].second.first;
        int y = vv[i].second.second;
        llint dist = vv[i].first;

        if (fin(x) != fin(y)) {
            graph2[x].push_back(make_pair(y, dist));
            graph2[y].push_back(make_pair(x, dist));
            merg(x, y);
        }
    }

    memset(bio, false, sizeof bio);
    dfs(1, -1, -inf, 1);
    for (int i = 1; i <= logo; i++) {
        for (int j = 1; j <= n; j++) {
            dp[i][j] = dp[i - 1][dp[i - 1][j]];
            sol[i][j] = max(sol[i - 1][j], sol[i - 1][dp[i - 1][j]]);
        }
    }

    for (int i = 0; i < q; i++) {
        int a, b;
        scanf("%d%d", &a, &b);

        int lc = lca(a, b);
        llint sol = max(cal(a, dub[a] - dub[lc]), cal(b, dub[b] - dub[lc]));
        printf("%lld\n", sol);
    }
    return 0;
}


#include <bits/stdc++.h>

using namespace std;
typedef long long llint;

const int maxn = 2e5+10;
const llint inf = 1LL << 60;

const int logo = 20;
const int off = 1 << logo;
const int treesiz = off << 1;

int n, m, k, q;
vector< pair<int, llint> > graph[maxn];
vector< pair< llint, pair<int, int> > > v, vv;
int parr[maxn];
llint dis[maxn];
set< pair<llint, int> > s;
vector< pair< int, llint> > graph2[maxn];
int dub[maxn];
int dp[logo + 10][maxn];
llint sol[logo + 10][maxn];
bool bio[maxn];

int fin(int x) {
    if (x == parr[x]) return x;
    else return parr[x] = fin(parr[x]);
}

void merg(int a, int b) {
    a = fin(a);
    b = fin(b);
    if (a == b) return;

    int ra = rand() % 2;
    if (ra == 0) parr[a] = b;
    else parr[b] = a;
}

void dfs(int x, int parr, llint dist, int du) {
    dp[0][x] = parr;
    sol[0][x] = dist;
    dub[x] = du;
    bio[x] = true;

    for (int i = 0; i < graph2[x].size(); i++) {
        int tren = graph2[x][i].first;
        llint cost = graph2[x][i].second;

        if (bio[tren]) continue;
        dfs(tren, x, cost, du + 1);
    }
}

int lift(int x, int val) {
    for (int i = 0; i <= logo; i++)
        if (val & (1 << i)) x = dp[i][x];
    return x;
}

int lca(int x, int y) {
    if (dub[x] > dub[y]) x = lift(x, dub[x] - dub[y]);
    if (dub[y] > dub[x]) y = lift(y, dub[y] - dub[x]);
    if (x == y) return x;

    for (int i = logo; i >= 0; i--) {
        if (dp[i][x] != dp[i][y]) {
            x = dp[i][x];
            y = dp[i][x];
        }
    }
    return dp[0][x];
}

llint cal(int x, int val) {
    llint out = -inf;
    for (int i = 0; i <= logo; i++) {
        if (val & (1 << i)) {
            out = max(out, sol[i][x]);
            x = dp[i][x];
        }
    }
    return out;
}

int main() {
    srand(time(0));
    scanf("%d%d%d%d", &n, &m, &k, &q);
    for (int i = 0; i < m; i++) {
        int a, b;
        llint c;
        scanf("%d%d%lld", &a, &b, &c);

        graph[a].push_back(make_pair(b, c));
        graph[b].push_back(make_pair(a, c));
        v.push_back(make_pair(c, make_pair(a, b)));
    }

    for (int i = 1; i <= n; i++) dis[i] = inf;
    for (int i = 1; i <= k; i++) {
        dis[i] = 0;
        s.insert(make_pair(0, i));
    }

    while (!s.empty()) {
        llint dist = s.begin()->first;
        int x = s.begin()->second;
        s.erase(s.begin());

        for (int i = 0; i < graph[x].size(); i++) {
            int tren = graph[x][i].first;
            llint cost = graph[x][i].second;

            if (dis[tren] > dist + cost) {
                s.erase(make_pair(dis[tren], tren));
                dis[tren] = dist + cost;
                s.insert(make_pair(dis[tren], tren));
            }
        }
    }

    for (int i = 0; i < m; i++) {
        int a = v[i].second.first;
        int b = v[i].second.second;
        llint ac = v[i].first;

        ac += dis[a] + dis[b];
        vv.push_back(make_pair(ac, make_pair(a, b)));
    }

    sort(vv.begin(), vv.end());
    for (int i = 1; i <= n; i++) parr[i] = i;
    for (int i = 0; i < m; i++) {
        int x = vv[i].second.first;
        int y = vv[i].second.second;
        llint dist = vv[i].first;

        if (fin(x) != fin(y)) {
            graph2[x].push_back(make_pair(y, dist));
            graph2[y].push_back(make_pair(x, dist));
            merg(x, y);
        }
    }

    memset(bio, false, sizeof bio);
    dfs(1, 0, -inf, 1);
    for (int i = 1; i <= logo; i++) {
        for (int j = 1; j <= n; j++) {
            dp[i][j] = dp[i - 1][dp[i - 1][j]];
            sol[i][j] = max(sol[i - 1][j], sol[i - 1][dp[i - 1][j]]);
        }
    }

    for (int i = 0; i < q; i++) {
        int a, b;
        scanf("%d%d", &a, &b);

        int lc = lca(a, b);
        llint sol = max(cal(a, dub[a] - dub[lc]), cal(b, dub[b] - dub[lc]));
        printf("%lld\n", sol);
    }
    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>

using namespace std;

#define debug(x) '[' << #x << " is: " << x << "] "
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

const int nax = 1e5 + 100;

vector<pair<ll,ll>> g[nax],tree[nax];
int par[nax][22],depth[nax];
ll mx[nax][22];
int n,m,k,q;
int fr[nax];
ll cost[nax];

void addedge(int u,int v,int w){
	g[u].push_back({v,w});
	g[v].push_back({u,w});
}

void dij(){
	priority_queue<pair<ll,int>> q;
	for(int i=1;i<=n;i++)cost[i] = 1e18;
	cost[1] = 0;
	fr[1] = 1;
	q.push({0,1});
	while(q.size()){
		int u = q.top().second;
		ll cst = -q.top().first;
		if(u <= k && fr[u] != u){
			assert(cst);
			tree[fr[u]].push_back({u,cst});
			tree[u].push_back({fr[u],cst});
			// cout << fr[u] << ' ' << u << ' ' << cst << endl;
			fr[u] = u;
			cost[u] = 0;
			cst = cost[u];
		}
		q.pop();
		if(cost[u] < cst)continue;
		for(pair<ll,int> curnode : g[u]){
			int v = curnode.first;
			ll w = curnode.second;
			ll ncst = cst + w;
			if(ncst >= cost[v])continue;
			cost[v] = ncst;
			fr[v] = fr[u];
			q.push({-cost[v],v});
		}
	}
}

void dfs(int u,int p){
	for(pair<ll,ll> curnode : tree[u]){
		int v = curnode.first;
		ll w = curnode.second;
		if(v == p)continue;
		depth[v] = depth[u] + 1;
		par[v][0] = u;
		mx[v][0] = w;
		dfs(v,u);
	}
}

pair<ll,int> kth(int u,int dis){
	ll big = 0;
	for(int k=20;k>=0;k--){
		if((dis>>k) & 1){
			big = max(big , mx[u][k]);
			assert(mx[u][k]);
			u = par[u][k];
		}
	}
	return {big,u};
}

ll lca(int u,int v){
	if(depth[u] < depth[v])swap(u,v);
	int dis = depth[u] - depth[v];
	pair<ll,int> nxt = kth(u,dis);
	ll big = nxt.first;
	u = nxt.second;
	// cout << u << ' ' << v << endl;
	if(u == v){
		return big;
	}
	for(int k=20;k>=0;k--){
		if(par[u][k] != par[v][k]){
			big = max(big , max(mx[v][k] , mx[u][k]));
			assert(mx[u][k]);
			assert(mx[v][k]);
			u = par[u][k];
			v = par[v][k];
		}
	}
	// cout << u << ' ' << v << endl;
	big = max(big , max(mx[u][0] , mx[v][0]));
	return big;
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.precision(10);
	cout << fixed;
	#ifndef ONLINE_JUDGE
		freopen("input.txt","r",stdin);
	#endif
	cin>>n>>m>>k>>q;
	for(int i=0;i<m;i++){
		int u,v,w;
		cin>>u>>v>>w;
		addedge(u,v,w);
	}
	dij();
	dfs(1,0);
	for(int k=1;k<20;k++){
		for(int i=1;i<=n;i++){
			par[i][k] = par[par[i][k-1]][k-1];
			mx[i][k] = max(mx[i][k-1] , mx[par[i][k-1]][k-1]);
		}
	}
	while(q--){
		int a,b;
		cin>>a>>b;
		cout << lca(a,b) << '\n';
	}
}


#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>

#define ll long long
#define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>

using namespace std;

const int nax = 1e5 + 1;
vector<pair<int, ll>> g[nax], tree[nax];
int par[nax][21], depth[nax];
ll mx[nax][21];
int n, m, k, q;
int fr[nax];
ll cost[nax];

void addedge(int u, int v, int w) {
    g[u].push_back({v, w});
    g[v].push_back({u, w});
}

void dij() {
    priority_queue<pair<ll, int>> q;
    for (int i = 1; i <= n; i++)cost[i] = 1e18;
    cost[1] = 0;
    fr[1] = 1;
    q.push({0, 1});
    while (q.size()) {
        int u = q.top().second;
        ll cst = -q.top().first;
        if (u <= k && fr[u] != u) {
            assert(cst);
            tree[fr[u]].push_back({u, cst});
            tree[u].push_back({fr[u], cst});
            // cout << fr[u] << ' ' << u << ' ' << cst << endl;
            fr[u] = u;
            cost[u] = 0;
            cst = cost[u];
        }
        q.pop();
        if (cost[u] < cst)continue;
        for (pair<int, int> curnode : g[u]) {
            int v = curnode.first;
            ll w = curnode.second;
            ll ncst = cst + w;
            if (ncst >= cost[v])continue;
            cost[v] = ncst;
            fr[v] = fr[u];
            q.push({-cost[v], v});
        }
    }
}

void dfs(int u, int p) {
    for (pair<int, ll> curnode : tree[u]) {
        int v = curnode.first;
        ll w = curnode.second;
        if (v == p)continue;
        depth[v] = depth[u] + 1;
        par[v][0] = u;
        mx[v][0] = w;
        dfs(v, u);
    }
}

pair<ll, int> kth(int u, int dis) {
    ll big = 0;
    for (int k = 20; k >= 0; k--) {
        if ((dis >> k) & 1) {
            big = max(big, mx[u][k]);
            assert(mx[u][k]);
            u = par[u][k];
        }
    }
    return {big, u};
}

ll lca(int u, int v) {
    if (depth[u] < depth[v])swap(u, v);
    int dis = depth[u] - depth[v];
    pair<ll, int> nxt = kth(u, dis);
    ll big = nxt.first;
    u = nxt.second;
    // cout << u << ' ' << v << endl;
    if (u == v) {
        return big;
    }
    for (int k = 20; k >= 0; k--) {
        if (par[u][k] != par[v][k]) {
            big = max(big, max(mx[v][k], mx[u][k]));
            assert(mx[u][k]);
            assert(mx[v][k]);
            u = par[u][k];
            v = par[v][k];
        }
    }
    // cout << u << ' ' << v << endl;
    big = max(big, max(mx[u][0], mx[v][0]));
    return big;
}

int main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n >> m >> k >> q;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        addedge(u, v, w);
    }
    dij();
    dfs(1, 0);
    for (int k = 1; k < 20; k++) {
        for (int i = 1; i <= n; i++) {
            par[i][k] = par[par[i][k - 1]][k - 1];
            mx[i][k] = max(mx[i][k - 1], mx[par[i][k - 1]][k - 1]);
        }
    }
    while (q--) {
        int a, b;
        cin >> a >> b;
        cout << lca(a, b) << endl;
    }
    return 0;
}


#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>

#define ll long long
#define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>

using namespace std;

const int nax = 1e5 + 1;
vector<pair<int, ll>> g[nax], tree[nax];
int par[nax][21], depth[nax];
ll mx[nax][21];
int n, m, k, q;
int fr[nax];
ll cost[nax];

void addedge(int u, int v, int w) {
    g[u].push_back({v, w});
    g[v].push_back({u, w});
}

void dij() {
    priority_queue<pair<int, int>> q;
    for (int i = 1; i <= n; i++)cost[i] = 1e18;
    cost[1] = 0;
    fr[1] = 1;
    q.push({0, 1});
    while (q.size()) {
        int u = q.top().second;
        ll cst = -q.top().first;
        if (u <= k && fr[u] != u) {
            assert(cst);
            tree[fr[u]].push_back({u, cst});
            tree[u].push_back({fr[u], cst});
            // cout << fr[u] << ' ' << u << ' ' << cst << endl;
            fr[u] = u;
            cost[u] = 0;
            cst = cost[u];
        }
        q.pop();
        if (cost[u] < cst)continue;
        for (pair<int, int> curnode : g[u]) {
            int v = curnode.first;
            ll w = curnode.second;
            ll ncst = cst + w;
            if (ncst >= cost[v])continue;
            cost[v] = ncst;
            fr[v] = fr[u];
            q.push({-cost[v], v});
        }
    }
}

void dfs(int u, int p) {
    for (pair<int, ll> curnode : tree[u]) {
        int v = curnode.first;
        ll w = curnode.second;
        if (v == p)continue;
        depth[v] = depth[u] + 1;
        par[v][0] = u;
        mx[v][0] = w;
        dfs(v, u);
    }
}

pair<ll, int> kth(int u, int dis) {
    ll big = 0;
    for (int k = 20; k >= 0; k--) {
        if ((dis >> k) & 1) {
            big = max(big, mx[u][k]);
            assert(mx[u][k]);
            u = par[u][k];
        }
    }
    return {big, u};
}

ll lca(int u, int v) {
    if (depth[u] < depth[v])swap(u, v);
    int dis = depth[u] - depth[v];
    pair<ll, int> nxt = kth(u, dis);
    ll big = nxt.first;
    u = nxt.second;
    // cout << u << ' ' << v << endl;
    if (u == v) {
        return big;
    }
    for (int k = 20; k >= 0; k--) {
        if (par[u][k] != par[v][k]) {
            big = max(big, max(mx[v][k], mx[u][k]));
            assert(mx[u][k]);
            assert(mx[v][k]);
            u = par[u][k];
            v = par[v][k];
        }
    }
    // cout << u << ' ' << v << endl;
    big = max(big, max(mx[u][0], mx[v][0]));
    return big;
}

int main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n >> m >> k >> q;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        addedge(u, v, w);
    }
    dij();
    dfs(1, 0);
    for (int k = 1; k < 20; k++) {
        for (int i = 1; i <= n; i++) {
            par[i][k] = par[par[i][k - 1]][k - 1];
            mx[i][k] = max(mx[i][k - 1], mx[par[i][k - 1]][k - 1]);
        }
    }
    while (q--) {
        int a, b;
        cin >> a >> b;
        cout << lca(a, b) << '\n';
    }
    return 0;
}