#include <bits/stdc++.h>

using namespace std;
#define ll long long

const int N = 1e5 + 5;
vector<pair<int, ll >> g[N];
int par[N];
vector<int> qur[N];
int a[3 * N], b[3 * N];
ll d[N];
int n;

void dij(int ks) {
    for (int i = ks + 1; i <= n; i++) d[i] = 1e15;
    priority_queue<pair<ll, int> > pq;
    for (int i = 1; i <= ks; i++) pq.push({0, i});
    while (pq.size()) {
        int node = pq.top().second;
        ll c = -pq.top().first;
        pq.pop();
        if (c != d[node]) continue;
        for (auto E:g[node]) {
            int v = E.first;
            int cs = E.second;
            if (d[v] > d[node] + cs) {
                d[v] = d[node] + cs;
                pq.push({-d[v], v});
            }
        }
    }
}

ll ans[3 * N];

int get(int n) {
    if (par[n] == n) return n;
    return par[n] = get(par[n]);
}

void merge(int u, int v, ll c) {
    int r1 = get(u);
    int r2 = get(v);
    if (r1 == r2) return;
    if (qur[r1].size() > qur[r2].size())swap(r1, r2);
    for (int i = 0; i < qur[r1].size(); i++) {
        int ind = qur[r1][i];
        int u = a[ind];
        int v = b[ind];
        u = get(u);
        v = get(v);
        if ((u == r1 && v == r2) || (u == r2 && v == r1)) {
            ans[ind] = c;
        } else if (u != v)qur[r2].push_back(ind);
    }
    par[r1] = r2;
    qur[r1].clear();
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int m, k, q;
    cin >> n >> m >> k >> q;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        g[u].emplace_back(v, w);
        g[v].emplace_back(u, w);
    }
    dij(k);
    vector<pair<ll, pair<int, int> > > edges;
    for (int i = 1; i <= n; i++) {
        for (auto E:g[i]) {
            int v = E.first;
            ll c = E.second;
            E.second = d[i] + d[v] + c;
            edges.push_back({E.second, {i, v}});
        }
    }
    for (int i = 0; i < q; i++) {
        cin >> a[i] >> b[i];
        qur[a[i]].push_back(i);
        qur[b[i]].push_back(i);
    }
    sort(edges.begin(), edges.end());
    iota(par, par + n + 1, 0);
    for (int i = 0; i < edges.size(); i++) {
        int u = edges[i].second.first;
        int v = edges[i].second.second;
        ll cost = edges[i].first;
        merge(u, v, cost);
    }
    for (int i = 0; i < q; i++) cout << ans[i] << "\n";
    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 + 5;
vector<pair<int, 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(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;
}


 #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<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<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(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;
}


#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) << '\n';
    }
    return 0;
}


#include <bits/stdc++.h>
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
using namespace std;

typedef long long ll;
typedef unsigned long long llu;
typedef pair<int, int> pii;
typedef pair<int, pii> piii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef pair<int, ll> pil;
typedef pair<string, int> psi;
typedef pair<char, int> pci;
typedef pair<int, char> pic;
const ll MOD = (ll)1e9 + 7;
const long double PI = 3.141592653589793238462643383279502884197;

ll fac[1] = {1}, inv[1] = {1};
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll mp(ll a,ll b){ll ret=1;while(b){if(b&1)ret=ret*a%MOD;a=a*a%MOD;b>>=1;}return ret;}
ll cmb(ll r, ll c) {return fac[r] * inv[c] % MOD * inv[r - c] % MOD;}

vector<pii> ov[100000];
int p[100000];

int find(int a) {
    if (p[a] == -1) return a;
    return p[a] = find(p[a]);
}

void merge(int a, int b) {
    a = find(a); b = find(b);
    if (a == b) return;
    p[b] = a;
}

ll dist[100000];
ll tdist[100000];
pii lr[100000];
pii qu[300000];
int wif[300000];    // 어느 루트로 부터 왔는 지.
priority_queue<pli, vector<pli>, greater<pli>> pq;
unordered_map<int, ll> um[100000];

struct edg {
    int u, v;
    ll co;
    bool operator< (const edg v2) const {
        return co < v2.co;
    };
};

int main() {
    memset(dist, 0x3f, sizeof(dist));
    memset(tdist, 0x3f, sizeof(tdist));

    int n, m, k, q;
    scanf("%d %d %d %d", &n, &m, &k, &q);

    int a, b, c;
    while (m--) {
        scanf("%d %d %d", &a, &b, &c);
        a--; b--;
        ov[a].push_back({c, b});
        ov[b].push_back({c, a});
    }

    for (int i = 0; i < k; i++) {
        pq.push({0, i});
        wif[i] = i;
        dist[i] = tdist[i] = 0;
    }

    pli tv;
    while (!pq.empty()) {
        tv = pq.top();
        pq.pop();

        if (tv.first != tdist[tv.second]) continue;

        for (pii i : ov[tv.second]) {
            if (tdist[i.second] > tv.first + i.first) {
                tdist[i.second] = tv.first + i.first;
                pq.push({tv.first+i.first, i.second});
                wif[i.second] = wif[tv.second];
            }
        }
    }

    for (int i = 0; i < k; i++) pq.push({0, i});
    while (!pq.empty()) {
        tv = pq.top();
        pq.pop();

        if (tv.first != dist[tv.second]) continue;

        for (pii i : ov[tv.second]) {
            if (wif[i.second] == wif[tv.second] && dist[i.second] > tv.first + i.first) {
                dist[i.second] = tv.first + i.first;
                pq.push({tv.first+i.first, i.second});
            }
            if (wif[i.second] != wif[tv.second]) {
                a = wif[i.second], b = wif[tv.second];
                if (a > b) swap(a, b);
                //printf("%d %d : %lld\n", a+1, b+1, i.first + tv.first+tdist[i.second]);
                //printf("%d : %lld %lld\n", i.second+1, i.first+tv.first, tdist[i.second]);
                if (um[a].find(b) == um[a].end()) um[a][b] = i.first+tv.first+tdist[i.second];
                else um[a][b] = min(um[a][b], i.first+tv.first+tdist[i.second]);
            }
        }
    }

    vector<edg> fi, se;
    vector<ll> x;
    for (int i = 0; i < n; i++)
        for (pil j : um[i])
            fi.push_back({i, j.first, j.second});

    sort(all(fi));
    memset(p, -1, sizeof(p));

    for (edg &i : fi) {
        if (find(i.u) != find(i.v)) {
            merge(i.u, i.v);
            se.push_back(i);
            x.push_back(i.co);

            // printf("%d %d : %lld\n", i.u, i.v, i.co);
        }
    }

    x.erase(unique(all(x)), x.end());
    for (int i = 0; i < q; i++) {
        scanf("%d %d", &a, &b);
        lr[i] = {0, sz(x) - 1};
        qu[i] = {a-1,b-1};
    }

    vector<pii> v;
    for (int cnt = 0; cnt < 25; cnt++) {
        memset(p, -1, sizeof(p));
        v.clear();

        for (int i = 0; i < q; i++)
            if (lr[i].first <= lr[i].second)
                v.push_back({(lr[i].first+lr[i].second)>>1, i});

        if (v.empty()) break;
        sort(all(v));

        int l = 0;
        for (pii i : v) {
            while (l < sz(se) && x[i.first] >= se[l].co) {
                merge(se[l].u, se[l].v);
                l++;
            }
            if (find(qu[i.second].first) == find(qu[i.second].second))
                lr[i.second].second = i.first-1;
            else lr[i.second].first = i.first+1;
        }
    }

    for (int i = 0; i < q; i++)
        printf("%lld\n", x[lr[i].first]);
}


#include <bits/stdc++.h>
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
using namespace std;

typedef long long ll;
typedef unsigned long long llu;
typedef pair<int, int> pii;
typedef pair<int, pii> piii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef pair<int, ll> pil;
typedef pair<string, int> psi;
typedef pair<char, int> pci;
typedef pair<int, char> pic;
const ll MOD = (ll)1e9 + 7;
const long double PI = 3.141592653589793238462643383279502884197;

ll fac[1] = {1}, inv[1] = {1};
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll mp(ll a,ll b){ll ret=1;while(b){if(b&1)ret=ret*a%MOD;a=a*a%MOD;b>>=1;}return ret;}
ll cmb(ll r, ll c) {return fac[r] * inv[c] % MOD * inv[r - c] % MOD;}

vector<pii> ov[100000];
int p[100000];

int find(int a) {
    if (p[a] == -1) return a;
    return p[a] = find(p[a]);
}

void merge(int a, int b) {
    a = find(a); b = find(b);
    if (a == b) return;
    p[b] = a;
}

ll tdist[100000];
pii lr[300000];
pii qu[300000];
int wif[100000];    // 어느 루트로 부터 왔는 지.
priority_queue<pli, vector<pli>, greater<pli>> pq;

struct edg {
    int u, v;
    ll co;
    bool operator< (const edg v2) const {
        return co < v2.co;
    };
};

int main() {
    memset(tdist, 0x3f, sizeof(tdist));

    int n, m, k, q;
    scanf("%d %d %d %d", &n, &m, &k, &q);

    int a, b, c;
    while (m--) {
        scanf("%d %d %d", &a, &b, &c);
        a--; b--;
        ov[a].push_back({c, b});
        ov[b].push_back({c, a});
    }

    for (int i = 0; i < k; i++) {
        pq.push({0, i});
        wif[i] = i;
        tdist[i] = 0;
    }

    pli tv;
    vector<edg> se;
    while (!pq.empty()) {
        tv = pq.top();
        pq.pop();

        if (tv.first != tdist[tv.second]) continue;

        for (pii i : ov[tv.second]) {
            if (tdist[i.second] > tv.first + i.first) {
                tdist[i.second] = tv.first + i.first;
                pq.push({tv.first+i.first, i.second});
                wif[i.second] = wif[tv.second];
            }
            if (wif[i.second] != wif[tv.second]) {
                a = wif[i.second], b = wif[tv.second];
                if (a > b) swap(a, b);
                se.push_back({a, b, i.first+tv.first+tdist[i.second]});
            }
        }
    }

    sort(all(se));
    memset(p, -1, sizeof(p));

    for (int i = 0; i < q; i++) {
        scanf("%d %d", &a, &b);
        lr[i] = {0, sz(se) - 1};
        qu[i] = {a-1,b-1};
    }

    vector<pii> v;
    for (int cnt = 0; cnt < 25; cnt++) {
        memset(p, -1, sizeof(p));
        v.clear();

        for (int i = 0; i < q; i++)
            if (lr[i].first <= lr[i].second)
                v.push_back({(lr[i].first+lr[i].second)>>1, i});

        if (v.empty()) break;
        sort(all(v));

        int l = 0;
        for (pii i : v) {
            while (l < sz(se) && se[i.first].co >= se[l].co) {
                merge(se[l].u, se[l].v);
                l++;
            }
            if (find(qu[i.second].first) == find(qu[i.second].second))
                lr[i.second].second = i.first-1;
            else lr[i.second].first = i.first+1;
        }
    }

    for (int i = 0; i < q; i++)
        printf("%lld\n", se[lr[i].first].co);
}


#include <bits/stdc++.h>
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
using namespace std;

typedef long long ll;
typedef unsigned long long llu;
typedef pair<int, int> pii;
typedef pair<int, pii> piii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef pair<int, ll> pil;
typedef pair<string, int> psi;
typedef pair<char, int> pci;
typedef pair<int, char> pic;
const ll MOD = (ll)1e9 + 7;
const long double PI = 3.141592653589793238462643383279502884197;

ll fac[1] = {1}, inv[1] = {1};
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll mp(ll a,ll b){ll ret=1;while(b){if(b&1)ret=ret*a%MOD;a=a*a%MOD;b>>=1;}return ret;}
ll cmb(ll r, ll c) {return fac[r] * inv[c] % MOD * inv[r - c] % MOD;}

vector<pii> ov[100000];
int p[100000];

int find(int a) {
    if (p[a] == -1) return a;
    return p[a] = find(p[a]);
}

void merge(int a, int b) {
    a = find(a); b = find(b);
    if (a == b) return;
    p[b] = a;
}

ll dist[100000];
ll tdist[100000];
pii lr[100000];
pii qu[100000];
int wif[100000];    // 어느 루트로 부터 왔는 지.
priority_queue<pli, vector<pli>, greater<pli>> pq;
unordered_map<int, ll> um[100000];

struct edg {
    int u, v;
    ll co;
    bool operator< (const edg v2) const {
        return co < v2.co;
    };
};

int main() {
    memset(p, -1, sizeof(p));
    memset(dist, 0x3f, sizeof(dist));
    memset(tdist, 0x3f, sizeof(tdist));

    int n, m, k, q;
    scanf("%d %d %d %d", &n, &m, &k, &q);

    int a, b, c;
    while (m--) {
        scanf("%d %d %d", &a, &b, &c);
        a--; b--;
        ov[a].push_back({c, b});
        ov[b].push_back({c, a});
    }

    for (int i = 0; i < k; i++) {
        pq.push({0, i});
        wif[i] = i;
        dist[i] = tdist[i] = 0;
    }

    // 최소인 정점이 미리 정해져야 하는걸까?
    pli tv;
    while (!pq.empty()) {
        tv = pq.top();
        pq.pop();

        if (tv.first != tdist[tv.second]) continue;

        for (pii i : ov[tv.second]) {
            if (tdist[i.second] > tv.first + i.first) {
                tdist[i.second] = tv.first + i.first;
                pq.push({tv.first+i.first, i.second});
                wif[i.second] = wif[tv.second];
            }
        }
    }

    // 그게 나면서 비용도 더 작으면 거기로 간다.
    // 내가 아니면 언오더드 맵에 기록한다.

    for (int i = 0; i < k; i++) pq.push({0, i});
    while (!pq.empty()) {
        tv = pq.top();
        pq.pop();

        if (tv.first != dist[tv.second]) continue;

        for (pii i : ov[tv.second]) {
            if (wif[i.second] == wif[tv.second] && dist[i.second] > tv.first + i.first) {
                dist[i.second] = tv.first + i.first;
                pq.push({tv.first+i.first, i.second});
            }
            if (wif[i.second] != wif[tv.second]) {
                a = wif[i.second], b = wif[tv.second];
                if (a > b) swap(a, b);
                //printf("%d %d : %lld\n", a+1, b+1, i.first + tv.first+tdist[i.second]);
                //printf("%d : %lld %lld\n", i.second+1, i.first+tv.first, tdist[i.second]);
                if (um[a].find(b) == um[a].end()) um[a][b] = i.first + tv.first+tdist[i.second];
                else um[a][b] = min(um[a][b], i.first + tv.first+tdist[i.second]);
            }
        }
    }

    vector<edg> fi, se;
    vector<ll> x;
    for (int i = 0; i < n; i++)
        for (pil j : um[i]) fi.push_back({i, j.first, j.second});

    sort(all(fi));
    for (edg &i : fi) {
        if (find(i.u) != find(i.v)) {
            merge(i.u, i.v);
            se.push_back(i);
            x.push_back(i.co);

            // printf("%d %d : %lld\n", i.u, i.v, i.co);
        }
    }

    x.erase(unique(all(x)), x.end());
    for (int i = 0; i < q; i++) {
        scanf("%d %d", &a, &b);
        lr[i] = {0, sz(x) - 1};
        qu[i] = {a-1,b-1};
    }

    vector<pii> v;
    for (int cnt = 0; cnt < 25; cnt++) {
        memset(p, -1, sizeof(p));
        v.clear();

        for (int i = 0; i < q; i++)
            if (lr[i].first <= lr[i].second)
                v.push_back({(lr[i].first+lr[i].second)>>1, i});

        if (v.empty()) break;
        sort(all(v));

        int l = 0;
        // 두정점,비용,
        // 이 비용을 업데이트 시켜주고나서,
        // 그것보다 비용이 이하인 쿼리들을 푼다..

        for (pii i : v) {
            while (l < sz(se) && x[i.first] >= se[l].co) {
                merge(se[l].u, se[l].v);
                l++;
            }
            if (find(qu[i.second].first) == find(qu[i.second].second))
                lr[i.second].second = i.first-1;
            else lr[i.second].first = i.first+1;
        }
    }

    for (int i = 0; i < q; i++) {
        printf("%lld\n", x[lr[i].first]);
    }
}


#include <bits/stdc++.h>
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
using namespace std;

typedef long long ll;
typedef unsigned long long llu;
typedef pair<int, int> pii;
typedef pair<int, pii> piii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef pair<int, ll> pil;
typedef pair<string, int> psi;
typedef pair<char, int> pci;
typedef pair<int, char> pic;
const ll MOD = (ll)1e9 + 7;
const long double PI = 3.141592653589793238462643383279502884197;

ll fac[1] = {1}, inv[1] = {1};
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll mp(ll a,ll b){ll ret=1;while(b){if(b&1)ret=ret*a%MOD;a=a*a%MOD;b>>=1;}return ret;}
ll cmb(ll r, ll c) {return fac[r] * inv[c] % MOD * inv[r - c] % MOD;}

vector<pii> ov[100000];
int p[100000];

int find(int a) {
    if (p[a] == -1) return a;
    return p[a] = find(p[a]);
}

void merge(int a, int b) {
    a = find(a); b = find(b);
    if (a == b) return;
    p[b] = a;
}

ll dist[100000];
ll tdist[100000];
pii lr[300000];
pii qu[300000];
int wif[100000];    // 어느 루트로 부터 왔는 지.
priority_queue<pli, vector<pli>, greater<pli>> pq;

struct edg {
    int u, v;
    ll co;
    bool operator< (const edg v2) const {
        return co < v2.co;
    };
};

int main() {
    memset(dist, 0x3f, sizeof(dist));
    memset(tdist, 0x3f, sizeof(tdist));

    int n, m, k, q;
    scanf("%d %d %d %d", &n, &m, &k, &q);

    int a, b, c;
    while (m--) {
        scanf("%d %d %d", &a, &b, &c);
        a--; b--;
        ov[a].push_back({c, b});
        ov[b].push_back({c, a});
    }

    for (int i = 0; i < k; i++) {
        pq.push({0, i});
        wif[i] = i;
        dist[i] = tdist[i] = 0;
    }

    pli tv;
    while (!pq.empty()) {
        tv = pq.top();
        pq.pop();

        if (tv.first != tdist[tv.second]) continue;

        for (pii i : ov[tv.second]) {
            if (tdist[i.second] > tv.first + i.first) {
                tdist[i.second] = tv.first + i.first;
                pq.push({tv.first+i.first, i.second});
                wif[i.second] = wif[tv.second];
            }
        }
    }

    for (int i = 0; i < k; i++) pq.push({0, i});
    vector<edg> fi, se;

    while (!pq.empty()) {
        tv = pq.top();
        pq.pop();

        if (tv.first != dist[tv.second]) continue;

        for (pii i : ov[tv.second]) {
            if (wif[i.second] == wif[tv.second] && dist[i.second] > tv.first + i.first) {
                dist[i.second] = tv.first + i.first;
                pq.push({tv.first+i.first, i.second});
            }
            if (wif[i.second] != wif[tv.second]) {
                a = wif[i.second], b = wif[tv.second];
                if (a > b) swap(a, b);
                fi.push_back({a, b, i.first+tv.first+tdist[i.second]});
            }
        }
    }

    vector<ll> x;

    sort(all(fi));
    memset(p, -1, sizeof(p));

    for (edg &i : fi) {
        if (find(i.u) != find(i.v)) {
            merge(i.u, i.v);
            se.push_back(i);
            x.push_back(i.co);

            // printf("%d %d : %lld\n", i.u, i.v, i.co);
        }
    }

    x.erase(unique(all(x)), x.end());
    for (int i = 0; i < q; i++) {
        scanf("%d %d", &a, &b);
        lr[i] = {0, sz(x) - 1};
        qu[i] = {a-1,b-1};
    }

    vector<pii> v;
    for (int cnt = 0; cnt < 25; cnt++) {
        memset(p, -1, sizeof(p));
        v.clear();

        for (int i = 0; i < q; i++)
            if (lr[i].first <= lr[i].second)
                v.push_back({(lr[i].first+lr[i].second)>>1, i});

        if (v.empty()) break;
        sort(all(v));

        int l = 0;
        for (pii i : v) {
            while (l < sz(se) && x[i.first] >= se[l].co) {
                merge(se[l].u, se[l].v);
                l++;
            }
            if (find(qu[i.second].first) == find(qu[i.second].second))
                lr[i.second].second = i.first-1;
            else lr[i.second].first = i.first+1;
        }
    }

    for (int i = 0; i < q; i++)
        printf("%lld\n", x[lr[i].first]);
}


#include <bits/stdc++.h>
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
using namespace std;

typedef long long ll;
typedef unsigned long long llu;
typedef pair<int, int> pii;
typedef pair<int, pii> piii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef pair<int, ll> pil;
typedef pair<string, int> psi;
typedef pair<char, int> pci;
typedef pair<int, char> pic;
const ll MOD = (ll)1e9 + 7;
const long double PI = 3.141592653589793238462643383279502884197;

ll fac[1] = {1}, inv[1] = {1};
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll mp(ll a,ll b){ll ret=1;while(b){if(b&1)ret=ret*a%MOD;a=a*a%MOD;b>>=1;}return ret;}
ll cmb(ll r, ll c) {return fac[r] * inv[c] % MOD * inv[r - c] % MOD;}

vector<pii> ov[100000];
int p[100000];

int find(int a) {
    if (p[a] == -1) return a;
    return p[a] = find(p[a]);
}

void merge(int a, int b) {
    a = find(a); b = find(b);
    if (a == b) return;
    p[b] = a;
}

ll dist[100000];
ll tdist[100000];
pii lr[100000];
pii qu[100000];
int wif[100000];    // 어느 루트로 부터 왔는 지.
priority_queue<pli, vector<pli>, greater<pli>> pq;

struct edg {
    int u, v;
    ll co;
    bool operator< (const edg v2) const {
        return co < v2.co;
    };
};

int main() {
    memset(dist, 0x3f, sizeof(dist));
    memset(tdist, 0x3f, sizeof(tdist));

    int n, m, k, q;
    scanf("%d %d %d %d", &n, &m, &k, &q);

    int a, b, c;
    while (m--) {
        scanf("%d %d %d", &a, &b, &c);
        a--; b--;
        ov[a].push_back({c, b});
        ov[b].push_back({c, a});
    }

    for (int i = 0; i < k; i++) {
        pq.push({0, i});
        wif[i] = i;
        dist[i] = tdist[i] = 0;
    }

    pli tv;
    while (!pq.empty()) {
        tv = pq.top();
        pq.pop();

        if (tv.first != tdist[tv.second]) continue;

        for (pii i : ov[tv.second]) {
            if (tdist[i.second] > tv.first + i.first) {
                tdist[i.second] = tv.first + i.first;
                pq.push({tv.first+i.first, i.second});
                wif[i.second] = wif[tv.second];
            }
        }
    }

    for (int i = 0; i < k; i++) pq.push({0, i});
    vector<edg> fi, se;

    while (!pq.empty()) {
        tv = pq.top();
        pq.pop();

        if (tv.first != dist[tv.second]) continue;

        for (pii i : ov[tv.second]) {
            if (wif[i.second] == wif[tv.second] && dist[i.second] > tv.first + i.first) {
                dist[i.second] = tv.first + i.first;
                pq.push({tv.first+i.first, i.second});
            }
            if (wif[i.second] != wif[tv.second]) {
                a = wif[i.second], b = wif[tv.second];
                if (a > b) swap(a, b);
                //printf("%d %d : %lld\n", a+1, b+1, i.first + tv.first+tdist[i.second]);
                //printf("%d : %lld %lld\n", i.second+1, i.first+tv.first, tdist[i.second]);
                fi.push_back({a, b, i.first+tv.first+tdist[i.second]});
            }
        }
    }

    vector<ll> x;

    sort(all(fi));
    memset(p, -1, sizeof(p));

    for (edg &i : fi) {
        if (find(i.u) != find(i.v)) {
            merge(i.u, i.v);
            se.push_back(i);
            x.push_back(i.co);

            // printf("%d %d : %lld\n", i.u, i.v, i.co);
        }
    }

    x.erase(unique(all(x)), x.end());
    for (int i = 0; i < q; i++) {
        scanf("%d %d", &a, &b);
        lr[i] = {0, sz(x) - 1};
        qu[i] = {a-1,b-1};
    }

    vector<pii> v;
    for (int cnt = 0; cnt < 25; cnt++) {
        memset(p, -1, sizeof(p));
        v.clear();

        for (int i = 0; i < q; i++)
            if (lr[i].first <= lr[i].second)
                v.push_back({(lr[i].first+lr[i].second)>>1, i});

        if (v.empty()) break;
        sort(all(v));

        int l = 0;
        for (pii i : v) {
            while (l < sz(se) && x[i.first] >= se[l].co) {
                merge(se[l].u, se[l].v);
                l++;
            }
            if (find(qu[i.second].first) == find(qu[i.second].second))
                lr[i.second].second = i.first-1;
            else lr[i.second].first = i.first+1;
        }
    }

    for (int i = 0; i < q; i++)
        printf("%lld\n", x[lr[i].first]);
}


#include <bits/stdc++.h>
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
using namespace std;

typedef long long ll;
typedef unsigned long long llu;
typedef pair<int, int> pii;
typedef pair<int, pii> piii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef pair<int, ll> pil;
typedef pair<string, int> psi;
typedef pair<char, int> pci;
typedef pair<int, char> pic;
const ll MOD = (ll)1e9 + 7;
const long double PI = 3.141592653589793238462643383279502884197;

ll fac[1] = {1}, inv[1] = {1};
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll mp(ll a,ll b){ll ret=1;while(b){if(b&1)ret=ret*a%MOD;a=a*a%MOD;b>>=1;}return ret;}
ll cmb(ll r, ll c) {return fac[r] * inv[c] % MOD * inv[r - c] % MOD;}

vector<pii> ov[100000];
int p[100000];

int find(int a) {
    if (p[a] == -1) return a;
    return p[a] = find(p[a]);
}

void merge(int a, int b) {
    a = find(a); b = find(b);
    if (a == b) return;
    p[b] = a;
}

ll tdist[100000];
pii lr[300000];
pii qu[300000];
int wif[100000];    // 어느 루트로 부터 왔는 지.
priority_queue<pli, vector<pli>, greater<pli>> pq;

struct edg {
    int u, v;
    ll co;
    bool operator< (const edg v2) const {
        return co < v2.co;
    };
};

int main() {
    memset(tdist, 0x3f, sizeof(tdist));

    int n, m, k, q;
    scanf("%d %d %d %d", &n, &m, &k, &q);

    int a, b, c;
    while (m--) {
        scanf("%d %d %d", &a, &b, &c);
        a--; b--;
        ov[a].push_back({c, b});
        ov[b].push_back({c, a});
    }

    for (int i = 0; i < k; i++) {
        pq.push({0, i});
        wif[i] = i;
        tdist[i] = 0;
    }

    pli tv;
    vector<edg> fi, se;
    while (!pq.empty()) {
        tv = pq.top();
        pq.pop();

        if (tv.first != tdist[tv.second]) continue;

        for (pii i : ov[tv.second]) {
            if (tdist[i.second] > tv.first + i.first) {
                tdist[i.second] = tv.first + i.first;
                pq.push({tv.first+i.first, i.second});
                wif[i.second] = wif[tv.second];
            }
            if (wif[i.second] != wif[tv.second]) {
                a = wif[i.second], b = wif[tv.second];
                if (a > b) swap(a, b);
                fi.push_back({a, b, i.first+tv.first+tdist[i.second]});
            }
        }
    }

    vector<ll> x;

    sort(all(fi));
    memset(p, -1, sizeof(p));

    for (edg &i : fi) {
        if (find(i.u) != find(i.v)) {
            merge(i.u, i.v);
            se.push_back(i);
            x.push_back(i.co);
        }
    }

    x.erase(unique(all(x)), x.end());
    for (int i = 0; i < q; i++) {
        scanf("%d %d", &a, &b);
        lr[i] = {0, sz(x) - 1};
        qu[i] = {a-1,b-1};
    }

    vector<pii> v;
    for (int cnt = 0; cnt < 25; cnt++) {
        memset(p, -1, sizeof(p));
        v.clear();

        for (int i = 0; i < q; i++)
            if (lr[i].first <= lr[i].second)
                v.push_back({(lr[i].first+lr[i].second)>>1, i});

        if (v.empty()) break;
        sort(all(v));

        int l = 0;
        for (pii i : v) {
            while (l < sz(se) && x[i.first] >= se[l].co) {
                merge(se[l].u, se[l].v);
                l++;
            }
            if (find(qu[i.second].first) == find(qu[i.second].second))
                lr[i.second].second = i.first-1;
            else lr[i.second].first = i.first+1;
        }
    }

    for (int i = 0; i < q; i++)
        printf("%lld\n", x[lr[i].first]);
}


#include <bits/stdc++.h>
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
using namespace std;

typedef long long ll;
typedef unsigned long long llu;
typedef pair<int, int> pii;
typedef pair<int, pii> piii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef pair<int, ll> pil;
typedef pair<string, int> psi;
typedef pair<char, int> pci;
typedef pair<int, char> pic;
const ll MOD = (ll)1e9 + 7;
const long double PI = 3.141592653589793238462643383279502884197;

ll fac[1] = {1}, inv[1] = {1};
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll mp(ll a,ll b){ll ret=1;while(b){if(b&1)ret=ret*a%MOD;a=a*a%MOD;b>>=1;}return ret;}
ll cmb(ll r, ll c) {return fac[r] * inv[c] % MOD * inv[r - c] % MOD;}

vector<pii> ov[100000];
int p[100000];

int find(int a) {
    if (p[a] == -1) return a;
    return p[a] = find(p[a]);
}

void merge(int a, int b) {
    a = find(a); b = find(b);
    if (a == b) return;
    p[b] = a;
}

ll dist[100000];
ll tdist[100000];
pii lr[100000];
pii qu[100000];
int wif[100000];    // 어느 루트로 부터 왔는 지.
priority_queue<pli, vector<pli>, greater<pli>> pq;
unordered_map<int, ll> um[100000];

struct edg {
    int u, v;
    ll co;
    bool operator< (const edg v2) const {
        return co < v2.co;
    };
};

int main() {
    memset(dist, 0x3f, sizeof(dist));
    memset(tdist, 0x3f, sizeof(tdist));

    int n, m, k, q;
    scanf("%d %d %d %d", &n, &m, &k, &q);

    int a, b, c;
    while (m--) {
        scanf("%d %d %d", &a, &b, &c);
        a--; b--;
        ov[a].push_back({c, b});
        ov[b].push_back({c, a});
    }

    for (int i = 0; i < k; i++) {
        pq.push({0, i});
        wif[i] = i;
        dist[i] = tdist[i] = 0;
    }

    pli tv;
    while (!pq.empty()) {
        tv = pq.top();
        pq.pop();

        if (tv.first != tdist[tv.second]) continue;

        for (pii i : ov[tv.second]) {
            if (tdist[i.second] > tv.first + i.first) {
                tdist[i.second] = tv.first + i.first;
                pq.push({tv.first+i.first, i.second});
                wif[i.second] = wif[tv.second];
            }
        }
    }

    for (int i = 0; i < k; i++) pq.push({0, i});
    while (!pq.empty()) {
        tv = pq.top();
        pq.pop();

        if (tv.first != dist[tv.second]) continue;

        for (pii i : ov[tv.second]) {
            if (wif[i.second] == wif[tv.second] && dist[i.second] > tv.first + i.first) {
                dist[i.second] = tv.first + i.first;
                pq.push({tv.first+i.first, i.second});
            }
            if (wif[i.second] != wif[tv.second]) {
                a = wif[i.second], b = wif[tv.second];
                if (a > b) swap(a, b);
                //printf("%d %d : %lld\n", a+1, b+1, i.first + tv.first+tdist[i.second]);
                //printf("%d : %lld %lld\n", i.second+1, i.first+tv.first, tdist[i.second]);
                if (um[a].find(b) == um[a].end()) um[a][b] = i.first+tv.first+tdist[i.second];
                else um[a][b] = min(um[a][b], i.first+tv.first+tdist[i.second]);
            }
        }
    }

    vector<edg> fi, se;
    vector<ll> x;
    for (int i = 0; i < n; i++)
        for (pil j : um[i])
            fi.push_back({i, j.first, j.second});

    sort(all(fi));
    memset(p, -1, sizeof(p));

    for (edg &i : fi) {
        if (find(i.u) != find(i.v)) {
            merge(i.u, i.v);
            se.push_back(i);
            x.push_back(i.co);

            // printf("%d %d : %lld\n", i.u, i.v, i.co);
        }
    }

    x.erase(unique(all(x)), x.end());
    for (int i = 0; i < q; i++) {
        scanf("%d %d", &a, &b);
        lr[i] = {0, sz(x) - 1};
        qu[i] = {a-1,b-1};
    }

    vector<pii> v;
    for (int cnt = 0; cnt < 25; cnt++) {
        memset(p, -1, sizeof(p));
        v.clear();

        for (int i = 0; i < q; i++)
            if (lr[i].first <= lr[i].second)
                v.push_back({(lr[i].first+lr[i].second)>>1, i});

        if (v.empty()) break;
        sort(all(v));

        int l = 0;
        for (pii i : v) {
            while (l < sz(se) && x[i.first] >= se[l].co) {
                merge(se[l].u, se[l].v);
                l++;
            }
            if (find(qu[i.second].first) == find(qu[i.second].second))
                lr[i.second].second = i.first-1;
            else lr[i.second].first = i.first+1;
        }
    }

    for (int i = 0; i < q; i++)
        printf("%lld\n", x[lr[i].first]);
}


/*
This is code of SuperJ6 for Codeforces.
Don't copy my code during f*kin' contests.

2.71828182845904523536
*/

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <set>
#include <string.h>
using namespace std;
#define endl '\n'
#define pi pair<long long, long long>

const long long inf = 1000000000007;
const int maxn = 100000;
int n, m, k, q;
long long rnk[maxn], par[maxn], dist[maxn];
vector<pi> graph[maxn];
set<pi> qry[maxn];
long long ans[maxn];

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

void dijkstra(){
	set<pi> pq;
	for(int i = 0; i < k; i++){
		dist[i] = 0, par[i] = i;
		pq.insert({0, i});
	}
	for(int i = k; i < n; i++){
		dist[i] = inf;
	}

	while(!pq.empty()){
		int c = (*pq.begin()).second, d = (*pq.begin()).first;
		pq.erase(pq.begin());

		for(pi i : graph[c]){
			if(d + i.second < dist[i.first]){
				pq.erase({dist[i.first], i.first});
				pq.insert({d + i.second, i.first});
				dist[i.first] = d + i.second;
				par[i.first] = par[c];
			}
		}
	}
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(NULL);

	cin >> n >> m >> k >> q;

	for(int i = 0; i < m; i++){
		long long u, v, w;
		cin >> u >> v >> w;
		u--, v--;
		graph[u].push_back({v, w});
		graph[v].push_back({u, w});
	}

	for(int i = 0; i < q; i++){
		int a, b;
		cin >> a >> b;
		a--, b--;
		qry[a].insert({b, i});
		qry[b].insert({a, i});
	}

	dijkstra();

	vector<pair<long long, pi>> pq;
	for(int i = 0; i < n; i++){
		for(pi p : graph[i]){
			if(par[i] < par[p.first]){
				pq.push_back({dist[i] + dist[p.first] + p.second, {par[i], par[p.first]}});
			}
		}
	}

	sort(pq.begin(), pq.end());

	for(int i = 0; i < pq.size(); i++){
		long long d = pq[i].first, x = pq[i].second.first, y = pq[i].second.second;
		x = find(x), y = find(y);

		if(x != y){
			if(rnk[x] < rnk[y]) swap(x, y);
			if(rnk[x] == rnk[y]) rnk[x]++;
			par[y] = x;

			while(!qry[y].empty()){
				pi p = *qry[y].begin();
				qry[y].erase(p);

				if(p.first == x){
					ans[p.second] = d;
					qry[x].erase({y, p.second});
				}else{
					qry[p.first].erase({y, p.second});
					qry[p.first].insert({x, p.second});
					qry[x].insert(p);
				}
			}
		}
	}

	for(int i = 0; i < q; i++) cout << ans[i] << endl;

	return 0;
}


/*
This is code of SuperJ6 for Codeforces.
Don't copy my code during f*kin' contests.

2.71828182845904523536
*/

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <set>
#include <string.h>
using namespace std;
#define endl '\n'
#define pi pair<long long, long long>

const long long inf = 1000000000000007;
const int maxn = 300000;
int n, m, k, q;
long long rnk[maxn], par[maxn], dist[maxn];
vector<pi> graph[maxn];
set<pi> qry[maxn];
long long ans[maxn];

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

void dijkstra(){
	set<pi> pq;
	for(int i = 0; i < k; i++){
		dist[i] = 0, par[i] = i;
		pq.insert({0, i});
	}
	for(int i = k; i < n; i++){
		dist[i] = inf;
	}

	while(!pq.empty()){
		long long c = (*pq.begin()).second, d = (*pq.begin()).first;
		pq.erase(pq.begin());

		for(pi i : graph[c]){
			if(d + i.second < dist[i.first]){
				pq.erase({dist[i.first], i.first});
				pq.insert({d + i.second, i.first});
				dist[i.first] = d + i.second;
				par[i.first] = par[c];
			}
		}
	}
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(NULL);

	cin >> n >> m >> k >> q;

	for(int i = 0; i < m; i++){
		long long u, v, w;
		cin >> u >> v >> w;
		u--, v--;
		graph[u].push_back({v, w});
		graph[v].push_back({u, w});
	}

	for(int i = 0; i < q; i++){
		int a, b;
		cin >> a >> b;
		a--, b--;
		qry[a].insert({b, i});
		qry[b].insert({a, i});
	}

	dijkstra();

	vector<pair<long long, pi>> pq;
	for(int i = 0; i < n; i++){
		for(pi p : graph[i]){
			if(par[i] < par[p.first]){
				pq.push_back({dist[i] + dist[p.first] + p.second, {par[i], par[p.first]}});
			}
		}
	}

	sort(pq.begin(), pq.end());

	for(int i = 0; i < pq.size(); i++){
		long long d = pq[i].first, x = pq[i].second.first, y = pq[i].second.second;
		x = find(x), y = find(y);

		if(x != y){
			if(rnk[x] < rnk[y]) swap(x, y);
			if(rnk[x] == rnk[y]) rnk[x]++;
			par[y] = x;

			while(!qry[y].empty()){
				pi p = *qry[y].begin();
				qry[y].erase(p);

				if(p.first == x){
					ans[p.second] = d;
					qry[x].erase({y, p.second});
				}else{
					qry[p.first].erase({y, p.second});
					qry[p.first].insert({x, p.second});
					qry[x].insert(p);
				}
			}
		}
	}

	for(int i = 0; i < q; i++) cout << ans[i] << endl;

	return 0;
}


/*
This is code of SuperJ6 for Codeforces.
Don't copy my code during f*kin' contests.

2.71828182845904523536
*/

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <set>
#include <string.h>
using namespace std;
#define endl '\n'
#define pi pair<long long, long long>

const long long inf = 1000000000007;
const int maxn = 300000;
int n, m, k, q;
long long rnk[maxn], par[maxn], dist[maxn];
vector<pi> graph[maxn];
set<pi> qry[maxn];
long long ans[maxn];

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

void dijkstra(){
	set<pi> pq;
	for(int i = 0; i < k; i++){
		dist[i] = 0, par[i] = i;
		pq.insert({0, i});
	}
	for(int i = k; i < n; i++){
		dist[i] = inf;
	}

	while(!pq.empty()){
		long long c = (*pq.begin()).second, d = (*pq.begin()).first;
		pq.erase(pq.begin());

		for(pi i : graph[c]){
			if(d + i.second < dist[i.first]){
				pq.erase({dist[i.first], i.first});
				pq.insert({d + i.second, i.first});
				dist[i.first] = d + i.second;
				par[i.first] = par[c];
			}
		}
	}
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(NULL);

	cin >> n >> m >> k >> q;

	for(int i = 0; i < m; i++){
		long long u, v, w;
		cin >> u >> v >> w;
		u--, v--;
		graph[u].push_back({v, w});
		graph[v].push_back({u, w});
	}

	for(int i = 0; i < q; i++){
		int a, b;
		cin >> a >> b;
		a--, b--;
		qry[a].insert({b, i});
		qry[b].insert({a, i});
	}

	dijkstra();

	vector<pair<long long, pi>> pq;
	for(int i = 0; i < n; i++){
		for(pi p : graph[i]){
			if(par[i] < par[p.first]){
				pq.push_back({dist[i] + dist[p.first] + p.second, {par[i], par[p.first]}});
			}
		}
	}

	sort(pq.begin(), pq.end());

	for(int i = 0; i < pq.size(); i++){
		long long d = pq[i].first, x = pq[i].second.first, y = pq[i].second.second;
		x = find(x), y = find(y);

		if(x != y){
			if(rnk[x] < rnk[y]) swap(x, y);
			if(rnk[x] == rnk[y]) rnk[x]++;
			par[y] = x;

			while(!qry[y].empty()){
				pi p = *qry[y].begin();
				qry[y].erase(p);

				if(p.first == x){
					ans[p.second] = d;
					qry[x].erase({y, p.second});
				}else{
					qry[p.first].erase({y, p.second});
					qry[p.first].insert({x, p.second});
					qry[x].insert(p);
				}
			}
		}
	}

	for(int i = 0; i < q; i++) cout << ans[i] << endl;

	return 0;
}


#include<bits/stdc++.h>

#define endl '\n'
#define fi first
#define se second
#define pb push_back
#define bit(s, i) (s & (1<<i))

using namespace std;

const int N = 3e5 + 5;
const int M = 1;
const int K = 1;
const int mod = 1e9+7;
const int inf = 2e9;
const long long Inf = 2e18;

typedef long long ll;
typedef pair < int, int > ii;
typedef pair < ll, int > li;
typedef pair < ll, ii > lii;
int n, m, k, q;

vector < ii > adj[N];
vector < lii > ed;
ll d[N];

void dick() {
	priority_queue < li, vector < li >, greater < li > > q;
	memset(d, 0x3f, sizeof d);

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

	while(q.size()) {
		li top = q.top();
		q.pop();
		ll pd = top.fi;
		int p = top.se;

		if(pd != d[p]) continue;

		for(ii u : adj[p]) if(pd + u.se < d[u.fi]) {
			d[u.fi] = pd + u.se;
			q.push({d[u.fi], u.fi});
		}
	}
}

vector < ii > re[N];

int par[N], res[N];
vector < int > con[N];

void init() {
	for(int i=1;i<=n;++i) {
		par[i] = i;
		con[i].pb(i);
	}
}

int get(int x) {
	if(x == par[x]) return x;
	return par[x] = get(par[x]);
}

void mix(int x, int y, ll w) {
	int u = get(x);
	int v = get(y);

	if(u == v) return;

	if(con[u].size() > con[v].size()) swap(u, v);

	for(int x : con[u]) {
		for(ii i : re[x]) {
			int id = i.se;
			int j = i.fi;
			if(get(j) == v) res[id] = w;
		}
		con[v].pb(x);
	}
	par[u] = v;
}

int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    // freopen("trash.inp","r",stdin);
    // freopen("trash.out","w",stdout);

    cin >> n >> m >> k >> q;
    for(int i=1;i<=m;++i) {
    	int u, v, w;
    	cin >> u >> v >> w;
    	adj[u].pb({v, w});
    	adj[v].pb({u, w});
    }

    dick();
    for(int i=1;i<=n;++i)
    for(ii x : adj[i]) {
    	ll dis = x.se + d[i] + d[x.fi];
    	ed.pb({dis, {i, x.fi}});
    }

   	for(int i=1;i<=q;++i) {
   		int u, v;
   		cin >> u >> v;
   		re[u].pb({v, i});
   		re[v].pb({u, i});
   	}

   	init();
   	sort(ed.begin(), ed.end());

   	for(auto x : ed) mix(x.se.fi, x.se.se, x.fi);

   	for(int i=1;i<=q;++i) cout << res[i] << endl;
}


#include<bits/stdc++.h>

#define endl '\n'
#define fi first
#define se second
#define pb push_back
#define bit(s, i) (s & (1<<i))
#define int long long
using namespace std;

const int N = 3e5 + 5;
const int M = 1;
const int K = 1;
const int mod = 1e9+7;
const int inf = 2e9;
const long long Inf = 2e18;

typedef long long ll;
typedef pair < int, int > ii;
typedef pair < ll, int > li;
typedef pair < ll, ii > lii;
int n, m, k, q;

vector < ii > adj[N];
vector < lii > ed;
ll d[N];

void dick() {
	priority_queue < li, vector < li >, greater < li > > q;
	memset(d, 0x3f, sizeof d);

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

	while(q.size()) {
		li top = q.top();
		q.pop();
		ll pd = top.fi;
		int p = top.se;

		if(pd != d[p]) continue;

		for(ii u : adj[p]) if(pd + u.se < d[u.fi]) {
			d[u.fi] = pd + u.se;
			q.push({d[u.fi], u.fi});
		}
	}
}

vector < ii > re[N];

int par[N], res[N];
vector < int > con[N];

void init() {
	for(int i=1;i<=n;++i) {
		par[i] = i;
		con[i].pb(i);
	}
}

int get(int x) {
	if(x == par[x]) return x;
	return par[x] = get(par[x]);
}

void mix(int x, int y, ll w) {
	int u = get(x);
	int v = get(y);

	if(u == v) return;

	if(con[u].size() > con[v].size()) swap(u, v);

	for(int x : con[u]) {
		for(ii i : re[x]) {
			int id = i.se;
			int j = i.fi;
			if(get(j) == v) res[id] = w;
		}
		con[v].pb(x);
	}
	par[u] = v;
}

signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    // freopen("trash.inp","r",stdin);
    // freopen("trash.out","w",stdout);

    cin >> n >> m >> k >> q;
    for(int i=1;i<=m;++i) {
    	int u, v, w;
    	cin >> u >> v >> w;
    	adj[u].pb({v, w});
    	adj[v].pb({u, w});
    }

    dick();
    for(int i=1;i<=n;++i)
    for(ii x : adj[i]) {
    	ll dis = x.se + d[i] + d[x.fi];
    	ed.pb({dis, {i, x.fi}});
    }

   	for(int i=1;i<=q;++i) {
   		int u, v;
   		cin >> u >> v;
   		re[u].pb({v, i});
   		re[v].pb({u, i});
   	}

   	init();
   	sort(ed.begin(), ed.end());

   	for(auto x : ed) mix(x.se.fi, x.se.se, x.fi);

   	for(int i=1;i<=q;++i) cout << res[i] << endl;
}


#include<bits/stdc++.h>

#define endl '\n'
#define fi first
#define se second
#define pb push_back
#define bit(s, i) (s & (1<<i))

using namespace std;

const int N = 2e5 + 5;
const int M = 1;
const int K = 1;
const int mod = 1e9+7;
const int inf = 2e9;
const long long Inf = 2e18;

typedef long long ll;
typedef pair < int, int > ii;
typedef pair < ll, int > li;
typedef pair < ll, ii > lii;
int n, m, k, q;

vector < ii > adj[N];
vector < lii > ed;
ll d[N];

void dick() {
	priority_queue < li, vector < li >, greater < li > > q;
	memset(d, 0x3f, sizeof d);

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

	while(q.size()) {
		li top = q.top();
		q.pop();
		ll pd = top.fi;
		int p = top.se;

		if(pd != d[p]) continue;

		for(ii u : adj[p]) if(pd + u.se < d[u.fi]) {
			d[u.fi] = pd + u.se;
			q.push({d[u.fi], u.fi});
		}
	}
}

vector < ii > re[N];

int par[N], res[N];
vector < int > con[N];

void init() {
	for(int i=1;i<=n;++i) {
		par[i] = i;
		con[i].pb(i);
	}
}

int get(int x) {
	if(x == par[x]) return x;
	return par[x] = get(par[x]);
}

void mix(int x, int y, ll w) {
	int u = get(x);
	int v = get(y);

	if(u == v) return;

	if(con[u].size() > con[v].size()) swap(u, v);

	for(int x : con[u]) {
		for(ii i : re[x]) {
			int id = i.se;
			int j = i.fi;
			if(get(j) == v) res[id] = w;
		}
		con[v].pb(x);
	}
	par[u] = v;
}

int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    // freopen("trash.inp","r",stdin);
    // freopen("trash.out","w",stdout);

    cin >> n >> m >> k >> q;
    for(int i=1;i<=m;++i) {
    	int u, v, w;
    	cin >> u >> v >> w;
    	adj[u].pb({v, w});
    	adj[v].pb({u, w});
    }

    dick();
    for(int i=1;i<=n;++i)
    for(ii x : adj[i]) {
    	ll dis = x.se + d[i] + d[x.fi];
    	ed.pb({dis, {i, x.fi}});
    }

   	for(int i=1;i<=q;++i) {
   		int u, v;
   		cin >> u >> v;
   		re[u].pb({v, i});
   		re[v].pb({u, i});
   	}

   	init();
   	sort(ed.begin(), ed.end());

   	for(auto x : ed) mix(x.se.fi, x.se.se, x.fi);

   	for(int i=1;i<=q;++i) cout << res[i] << endl;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef pair<LL, int> pli;
typedef pair<LL, pii> plii;
vector<pii> g[100005];
LL dp[100005];
vector<plii> edges;
int u[300005], v[300005];
LL lo[300005], hi[300005], mid[300005], ans[300005];
int p[100005];
int root(int a){
    return p[a] == a?a:(p[a]=root(p[a]));
}
void merge(int a, int b){
    a = root(a), b = root(b);
    if(a != b) p[a] = b;
}
int main(){
    int n, m, k, q, a, b, w;
    scanf("%d%d%d%d", &n, &m, &k, &q);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d", &a, &b, &w);
        g[a].push_back(pli(w, b));
        g[b].push_back(pli(w, a));
        edges.push_back(plii(w, pii(a, b)));
    }
    memset(dp, -1, sizeof(dp));
    priority_queue<pli> pq;
    for(int i=1;i<=k;i++) pq.push(pli(0, i)), dp[i] = 0;
    while(!pq.empty()){
        LL val = -pq.top().first;
        int u = pq.top().second;
        pq.pop();
        if(val != dp[u]) continue;
        for(int i=0;i<g[u].size();i++){
            int v = g[u][i].second, w = g[u][i].first;
            if(dp[v] == -1 || dp[v] > dp[u] + w){
                dp[v] = dp[u] + w;
                pq.push(pli(-dp[v], v));
            }
        }
    }
    for(int i=0;i<edges.size();i++){
        int u = edges[i].second.first, v = edges[i].second.second;
        edges[i].first = dp[u] + dp[v] + edges[i].first;
    }
    for(int i=1;i<=q;i++){
        scanf("%d%d", &u[i], &v[i]);
        lo[i] = 1, hi[i] = 1e18;
    }
    sort(edges.begin(), edges.end());
    int x = 0;
    while(1){
        bool ok = 1;
        vector<pli> cur;
        for(int i=1;i<=q;i++){
            if(lo[i] > hi[i]) continue;
            mid[i] = (lo[i]+hi[i])/2;
            ok = 0;
            cur.push_back(pli(mid[i], i));
        }
        if(ok) break;
        for(int i=1;i<=n;i++) p[i] = i;
        sort(cur.begin(), cur.end());
        int l = 0;
        for(int i=0;i<edges.size();i++){
            LL val = edges[i].first;
            int a = edges[i].second.first, b = edges[i].second.second;
            while(l < cur.size() && cur[l].first < val){
                int idx = cur[l].second;
                if(root(u[idx]) == root(v[idx])){
                    ans[idx] = mid[idx];
                    hi[idx] = mid[idx]-1;
                }
                else{
                    lo[idx] = mid[idx]+1;
                }
                l++;
            }
            merge(a, b);
        }

        while(l < cur.size()){
            int idx = cur[l].second;
            if(root(u[idx]) == root(v[idx])){
                ans[idx] = mid[idx];
                hi[idx] = mid[idx]-1;
            }
            else{
                lo[idx] = mid[idx]+1;
            }
            l++;
        }
    }
    for(int i=1;i<=q;i++) printf("%lld\n", ans[i]);
}


#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef pair<LL, int> pli;
typedef pair<LL, pii> plii;
vector<pii> g[100005];
LL dp[100005];
vector<plii> edges;
int u[300005], v[300005];
LL lo[300005], hi[300005], mid[300005], ans[300005];
int p[100005];
int root(int a){
    return p[a] == a?a:(p[a]=root(p[a]));
}
void merge(int a, int b){
    a = root(a), b = root(b);
    if(a != b) p[a] = b;
}
int main(){
    int n, m, k, q, a, b, w;
    scanf("%d%d%d%d", &n, &m, &k, &q);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d", &a, &b, &w);
        g[a].push_back(pli(w, b));
        g[b].push_back(pli(w, a));
        edges.push_back(plii(w, pii(a, b)));
    }
    memset(dp, -1, sizeof(dp));
    priority_queue<pli> pq;
    for(int i=1;i<=k;i++) pq.push(pli(0, i)), dp[i] = 0;
    while(!pq.empty()){
        LL val = -pq.top().first;
        int u = pq.top().second;
        pq.pop();
        if(val != dp[u]) continue;
        for(int i=0;i<g[u].size();i++){
            int v = g[u][i].second, w = g[u][i].first;
            if(dp[v] == -1 || dp[v] > dp[u] + w){
                dp[v] = dp[u] + w;
                pq.push(pli(-dp[v], v));
            }
        }
    }
    vector<LL> weights;
    for(int i=0;i<edges.size();i++){
        int u = edges[i].second.first, v = edges[i].second.second;
        edges[i].first = dp[u] + dp[v] + edges[i].first;
        weights.push_back(edges[i].first);
    }
    sort(weights.begin(), weights.end());
    weights.erase(unique(weights.begin(), weights.end()), weights.end());
    for(int i=1;i<=q;i++){
        scanf("%d%d", &u[i], &v[i]);
        lo[i] = 0, hi[i] = weights.size()-1;
    }
    sort(edges.begin(), edges.end());
    int x = 0;
    while(1){
        bool ok = 1;
        vector<pli> cur;
        for(int i=1;i<=q;i++){
            if(lo[i] > hi[i]) continue;
            mid[i] = (lo[i]+hi[i])/2;
            ok = 0;
            cur.push_back(pli(mid[i], i));
        }
        if(ok) break;
        for(int i=1;i<=n;i++) p[i] = i;
        sort(cur.begin(), cur.end());
        int l = 0;
        for(int i=0;i<edges.size();i++){
            LL val = edges[i].first;
            int a = edges[i].second.first, b = edges[i].second.second;
            while(l < cur.size() && weights[cur[l].first] < val){
                int idx = cur[l].second;
                if(root(u[idx]) == root(v[idx])){
                    ans[idx] = weights[mid[idx]];
                    hi[idx] = mid[idx]-1;
                }
                else{
                    lo[idx] = mid[idx]+1;
                }
                l++;
            }
            merge(a, b);
        }

        while(l < cur.size()){
            int idx = cur[l].second;
            if(root(u[idx]) == root(v[idx])){
                ans[idx] = weights[mid[idx]];
                hi[idx] = mid[idx]-1;
            }
            else{
                lo[idx] = mid[idx]+1;
            }
            l++;
        }
    }
    for(int i=1;i<=q;i++) printf("%lld\n", ans[i]);
}


#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
typedef pair<long long, int> pii2;
typedef pair<long long, pii> pii3;
vector<pii> g[100002];
vector<pii2> gt[100002];

long long dp[100002];
int a[300002], b[300002], c[300002];
int p[100002];
int root(int a){
    return p[a] == a?a:(p[a]=root(p[a]));
}
void merge(int a, int b){
    a = root(a), b = root(b);
    if(a != b) p[a] = b;
}

int par[17][100002], D[100002];
long long mx[17][100002];
void dfs(int u, int p, int d, long long w){
    D[u] = d;
    par[0][u] = p;
    mx[0][u] = w;
    for(int i=0;i<gt[u].size();i++){
        int v = gt[u][i].second;
        long long w = gt[u][i].first;
        if(v == p) continue;
        dfs(v, u, d+1, w);
    }
}
int LCA(int a, int b){
    if(D[b] > D[a]) swap(a, b);
    int diff = D[a] - D[b];
    for(int i=16;i>=0;i--){
        if((diff>>i)&1) a = par[i][a];
    }
    if(a == b) return a;
    for(int i=16;i>=0;i--){
        if(par[i][a] != par[i][b]) a = par[i][a], b = par[i][b];
    }
    return par[0][a];
}
long long jump(int a, int b){
    if(a == b) return 0;
    int d = D[a] - D[b];
    long long ans = 0;
    for(int i=16;i>=0;i--){
        if((d>>i)&1){
            ans = max(ans, mx[i][a]);
            a = par[i][a];
        }
    }
    return ans;
}

int main(){
    int n, m, k, q;
    scanf("%d%d%d%d", &n, &m, &k, &q);
    for(int i=1;i<=n;i++) p[i] = i;
    for(int i=1;i<=m;i++){
        scanf("%d%d%d", &a[i], &b[i], &c[i]);
        g[a[i]].push_back(pii(b[i], c[i]));
        g[b[i]].push_back(pii(a[i], c[i]));
    }

    memset(dp, -1, sizeof(dp));
    priority_queue<pii2> pq;
    for(int i=1;i<=k;i++) pq.push(make_pair(0, i)), dp[i] = 0;
    while(!pq.empty()){
        long long val = -pq.top().first;
        int u = pq.top().second;
        pq.pop();
        if(val != dp[u]) continue;
        for(int i=0;i<g[u].size();i++){
            int v = g[u][i].first, w = g[u][i].second;
            if(dp[v] == -1 || dp[v] > dp[u] + w){
                dp[v] = dp[u] + w;
                pq.push(make_pair(-dp[v], v));
            }
        }
    }

    vector<pii3> E;
    for(int i=1;i<=m;i++){
        E.push_back(make_pair(dp[a[i]] + dp[b[i]] + c[i], make_pair(a[i], b[i])));
    }
    sort(E.begin(), E.end());
    for(int i=0;i<E.size();i++){
        int a = E[i].second.first, b = E[i].second.second;
        long long val = E[i].first;
        if(root(a) == root(b)) continue;
        merge(a, b);
        gt[a].push_back(make_pair(val, b));
        gt[b].push_back(make_pair(val, a));
    }
    dfs(1, 0, 0, 0);
    for(int j=1;j<17;j++){
        for(int i=1;i<=n;i++){
            if(par[j-1][i] != 0){
                par[j][i] = par[j-1][par[j-1][i]];
                mx[j][i] = max(mx[j-1][i], mx[j-1][par[j-1][i]]);
            }
        }
    }

    for(int i=1;i<=q;i++){
        int a, b, c;
        scanf("%d%d", &a, &b);
        c = LCA(a, b);
        printf("%lld\n", max(jump(a, c), jump(b, c)));
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef pair<LL, int> pli;
typedef pair<LL, pii> plii;
vector<pii> g[100005];
LL dp[100005];
vector<plii> edges;
int u[300005], v[300005];
LL lo[300005], hi[300005], mid[300005], ans[300005];
int p[100005];
int root(int a){
    return p[a] == a?a:(p[a]=root(p[a]));
}
void merge(int a, int b){
    a = root(a), b = root(b);
    if(a != b) p[a] = b;
}
int main(){
    int n, m, k, q, a, b, w;
    scanf("%d%d%d%d", &n, &m, &k, &q);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d", &a, &b, &w);
        g[a].push_back(pli(w, b));
        g[b].push_back(pli(w, a));
        edges.push_back(plii(w, pii(a, b)));
    }
    memset(dp, -1, sizeof(dp));
    priority_queue<pli> pq;
    for(int i=1;i<=k;i++) pq.push(pli(0, i)), dp[i] = 0;
    while(!pq.empty()){
        LL val = -pq.top().first;
        int u = pq.top().second;
        pq.pop();
        if(val != dp[u]) continue;
        for(int i=0;i<g[u].size();i++){
            int v = g[u][i].second, w = g[u][i].first;
            if(dp[v] == -1 || dp[v] > dp[u] + w){
                dp[v] = dp[u] + w;
                pq.push(pli(-dp[v], v));
            }
        }
    }
    for(int i=0;i<edges.size();i++){
        int u = edges[i].second.first, v = edges[i].second.second;
        edges[i].first = dp[u] + dp[v] + edges[i].first;
    }
    for(int i=1;i<=q;i++){
        scanf("%d%d", &u[i], &v[i]);
        lo[i] = 1, hi[i] = 1e13;
    }
    sort(edges.begin(), edges.end());
    int x = 0;
    while(1){
        bool ok = 1;
        vector<pli> cur;
        for(int i=1;i<=q;i++){
            if(lo[i] > hi[i]) continue;
            mid[i] = (lo[i]+hi[i])/2;
            ok = 0;
            cur.push_back(pli(mid[i], i));
        }
        if(ok) break;
        for(int i=1;i<=n;i++) p[i] = i;
        sort(cur.begin(), cur.end());
        int l = 0;
        for(int i=0;i<edges.size();i++){
            LL val = edges[i].first;
            int a = edges[i].second.first, b = edges[i].second.second;
            while(l < cur.size() && cur[l].first < val){
                int idx = cur[l].second;
                if(root(u[idx]) == root(v[idx])){
                    ans[idx] = mid[idx];
                    hi[idx] = mid[idx]-1;
                }
                else{
                    lo[idx] = mid[idx]+1;
                }
                l++;
            }
            merge(a, b);
        }

        while(l < cur.size()){
            int idx = cur[l].second;
            if(root(u[idx]) == root(v[idx])){
                ans[idx] = mid[idx];
                hi[idx] = mid[idx]-1;
            }
            else{
                lo[idx] = mid[idx]+1;
            }
            l++;
        }
    }
    for(int i=1;i<=q;i++) printf("%lld\n", ans[i]);
}


#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long int llint;
llint dist[100005];
llint n,m,k,q,ind[100005],parent[100005],depth[100005],maxi[100005][25],parent2[100005][25],sol[300005];
vector <pair<int,int> > v[100005];
vector <pair<int,llint> > v2[100005];
set <pair<llint,int> > s;
map <pair<int,int>,llint> m1;
vector <pair<int,pair<int,int> > > e;
vector <pair<llint,pair<int,int> > > e2;
set <int> s1[100005];
void dijkstra() {
	for(int i=0;i<n;i++) {
		dist[i]=1e18;
		if(i<k) {
            dist[i]=0;
            ind[i]=i;
		}
		s.insert(make_pair(dist[i],i));
	}
	while(!s.empty()) {
		llint d=(*s.begin()).first,x=(*s.begin()).second;
		s.erase(s.begin());
		for(int i=0;i<v[x].size();i++) {
			if(d+v[x][i].second<dist[v[x][i].first]) {
				ind[v[x][i].first]=ind[x];
				s.erase(make_pair(dist[v[x][i].first],v[x][i].first));
				dist[v[x][i].first]=d+v[x][i].second;
				s.insert(make_pair(dist[v[x][i].first],v[x][i].first));
			}
		}
	}
}
int find_par(int x) {
	if(x==parent[x]) return x;
	int par=find_par(parent[x]);
	parent[x]=par;
	return par;
}
void spoji(int x,int y,llint a) {
	x=find_par(x);
	y=find_par(y);
	if(x==y) return;
	if(depth[x]==depth[y]) depth[x]+=1;
	if(depth[x]>depth[y]) parent[y]=x;
	else parent[x]=y;
	if(s1[x].size()>s1[y].size()) {
		for(set <int>::iterator it=s1[y].begin();it!=s1[y].end();it++) {
			if(s1[x].find(*it)!=s1[x].end()) sol[*it]=a;
			s1[x].insert(*it);
		}
		s1[y].clear();
		if(x!=parent[y]) swap(s1[x],s1[y]);
	}
	else {
		for(set <int>::iterator it=s1[x].begin();it!=s1[x].end();it++) {
			if(s1[y].find(*it)!=s1[y].end()) sol[*it]=a;
			s1[y].insert(*it);
		}
		s1[x].clear();
		if(y!=parent[x]) swap(s1[x],s1[y]);
	}
}
int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m >> k >> q;
	for(int i=0;i<m;i++) {
		int a,b,w;
		cin >> a >> b >> w;
		v[a-1].push_back(make_pair(b-1,w));
		v[b-1].push_back(make_pair(a-1,w));
		e.push_back(make_pair(w,make_pair(a-1,b-1)));
	}
	dijkstra();
	for(int i=0;i<m;i++) {
		int x=e[i].second.first,y=e[i].second.second;
		if(ind[x]==ind[y]) continue;
		if(m1[make_pair(ind[x],ind[y])]==0 or dist[x]+e[i].first+dist[y]<m1[make_pair(ind[x],ind[y])]) {
			m1[make_pair(ind[x],ind[y])]=dist[x]+e[i].first+dist[y];
			m1[make_pair(ind[y],ind[x])]=dist[x]+e[i].first+dist[y];
		}
	}
	for(int i=0;i<m;i++) {
		int x=e[i].second.first,y=e[i].second.second;
		if(ind[x]==ind[y] or m1[make_pair(ind[x],ind[y])]==0) continue;
		e2.push_back(make_pair(m1[make_pair(ind[x],ind[y])],make_pair(ind[x],ind[y])));
		m1[make_pair(ind[x],ind[y])]=0;
		m1[make_pair(ind[y],ind[x])]=0;
	}
	sort(e2.begin(),e2.end());
	for(int i=0;i<k;i++) parent[i]=i;
	for(int i=0;i<q;i++) {
		int a,b;
		cin >> a >> b;
		s1[ind[a-1]].insert(i);
		s1[ind[b-1]].insert(i);
	}
	for(int i=0;i<e2.size();i++) {
		int x=e2[i].second.first,y=e2[i].second.second;
		if(find_par(x)==find_par(y)) continue;
		spoji(x,y,e2[i].first);
	}
	for(int i=0;i<q;i++) {
		cout << sol[i] << "\n";
	}
	return 0;
}


#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long int llint;
llint dist[100005];
int n,m,k,q,ind[100005],parent[100005],depth[100005],maxi[100005][25],parent2[100005][25];
vector <pair<int,int> > v[100005];
vector <pair<int,int> > v2[100005];
set <pair<llint,int> > s;
map <pair<int,int>,int> m1;
vector <pair<int,pair<int,int> > > e;
vector <pair<int,pair<int,int> > > e2;
void dijkstra() {
	for(int i=0;i<n;i++) {
		dist[i]=1e18;
		if(i<k) {
            dist[i]=0;
            ind[i]=i;
		}
		s.insert(make_pair(dist[i],i));
	}
	while(!s.empty()) {
		llint d=(*s.begin()).first,x=(*s.begin()).second;
		s.erase(s.begin());
		for(int i=0;i<v[x].size();i++) {
			if(d+v[x][i].second<dist[v[x][i].first]) {
				ind[v[x][i].first]=ind[x];
				s.erase(make_pair(dist[v[x][i].first],v[x][i].first));
				dist[v[x][i].first]=d+v[x][i].second;
				s.insert(make_pair(dist[v[x][i].first],v[x][i].first));
			}
		}
        /*for(int i=0;i<n;i++) {
            cout << dist[i] << " ";
        }
        cout << "\n";*/
	}
	/*for(int i=0;i<n;i++) {
        cout << dist[i] << " ";
	}
	cout << "\n";*/
}
int find_par(int x) {
	if(x==parent[x]) return x;
	int par=find_par(parent[x]);
	parent[x]=par;
	return par;
}
void spoji(int x,int y) {
	x=find_par(x);
	y=find_par(y);
	if(x==y) return;
	if(depth[x]==depth[y]) depth[x]+=1;
	if(depth[x]>depth[y]) parent[y]=x;
	else parent[x]=y;
}
void dfs(int x,int par,int d1) {
	parent2[x][0]=par;
	depth[x]=d1;
	//cout << x << " " << par << "\n";
	for(int i=0;i<v2[x].size();i++) {
		if(v2[x][i].first==par) continue;
		maxi[v2[x][i].first][0]=v2[x][i].second;
		//cout << v2[x][i].first << " " << maxi[v2[x][i].first][0] << "\n";
		dfs(v2[x][i].first,x,d1+1);
	}
}
int lca(int a,int b) {
	if(depth[a]<depth[b]) swap(a,b);
	int sol=0;
	for(int i=0;i<20;i++) {
		if((depth[a]-depth[b]) & (1 << i)) {
			sol=max(sol,maxi[a][i]);
			a=parent2[a][i];
		}
	}
	if(a==b) return sol;
	for(int i=19;i>=0;i--) {
		if(parent2[a][i]==parent2[b][i]) continue;
		sol=max(sol,max(maxi[a][i],maxi[b][i]));
		a=parent2[a][i];
		b=parent2[b][i];
	}
	return max(sol,max(maxi[a][0],maxi[b][0]));
}
int main()
{
	cin >> n >> m >> k >> q;
	//std::cout << "bok";
	for(int i=0;i<m;i++) {
		int a,b,w;
		cin >> a >> b >> w;
		v[a-1].push_back(make_pair(b-1,w));
		v[b-1].push_back(make_pair(a-1,w));
		e.push_back(make_pair(w,make_pair(a-1,b-1)));
	}
	dijkstra();
	for(int i=0;i<m;i++) {
		int x=e[i].second.first,y=e[i].second.second;
		if(ind[x]==ind[y]) continue;
		if(m1[make_pair(ind[x],ind[y])]==0 or dist[x]+e[i].first+dist[y]<m1[make_pair(ind[x],ind[y])]) {
			m1[make_pair(ind[x],ind[y])]=dist[x]+e[i].first+dist[y];
			m1[make_pair(ind[y],ind[x])]=dist[x]+e[i].first+dist[y];
		}
	}
	for(int i=0;i<m;i++) {
		int x=e[i].second.first,y=e[i].second.second;
		if(ind[x]==ind[y] or m1[make_pair(ind[x],ind[y])]==0) continue;
		e2.push_back(make_pair(m1[make_pair(ind[x],ind[y])],make_pair(ind[x],ind[y])));
		m1[make_pair(ind[x],ind[y])]=0;
		m1[make_pair(ind[y],ind[x])]=0;
	}
	sort(e2.begin(),e2.end());
	for(int i=0;i<k;i++) parent[i]=i;
	for(int i=0;i<e2.size();i++) {
		int x=e2[i].second.first,y=e2[i].second.second;
		if(find_par(x)==find_par(y)) continue;
		spoji(x,y);
		v2[x].push_back(make_pair(y,e2[i].first));
		v2[y].push_back(make_pair(x,e2[i].first));
		//cout << x << " " << y << " " << e2[i].first << "\n";
	}
	memset(depth,0,sizeof(depth));
	dfs(0,0,0);
	for(int i=1;i<20;i++) {
		for(int j=0;j<n;j++) {
			parent2[j][i]=parent2[parent2[j][i-1]][i-1];
			maxi[j][i]=max(maxi[parent2[j][i-1]][i-1],maxi[j][i-1]);
		}
	}
	//cout << maxi[1][0] << " " << maxi[2][0] << "\n";
	/*for(int i=0;i<n;i++) {
        cout << ind[i] << " ";
	}
	cout << "\n";*/
	for(int i=0;i<q;i++) {
		int a,b;
		cin >> a >> b;
		cout << lca(ind[a-1],ind[b-1]) << "\n";
	}
	return 0;
}


#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long int llint;
llint dist[100005];
llint n,m,k,q,ind[100005],parent[100005],depth[100005],maxi[100005][25],parent2[100005][25];
vector <pair<int,int> > v[100005];
vector <pair<int,llint> > v2[100005];
set <pair<llint,int> > s;
map <pair<int,int>,llint> m1;
vector <pair<int,pair<int,int> > > e;
vector <pair<llint,pair<int,int> > > e2;
void dijkstra() {
	for(int i=0;i<n;i++) {
		dist[i]=1e18;
		if(i<k) {
            dist[i]=0;
            ind[i]=i;
		}
		s.insert(make_pair(dist[i],i));
	}
	while(!s.empty()) {
		llint d=(*s.begin()).first,x=(*s.begin()).second;
		s.erase(s.begin());
		for(int i=0;i<v[x].size();i++) {
			if(d+v[x][i].second<dist[v[x][i].first]) {
				ind[v[x][i].first]=ind[x];
				s.erase(make_pair(dist[v[x][i].first],v[x][i].first));
				dist[v[x][i].first]=d+v[x][i].second;
				s.insert(make_pair(dist[v[x][i].first],v[x][i].first));
			}
		}
        /*for(int i=0;i<n;i++) {
            cout << dist[i] << " ";
        }
        cout << "\n";*/
	}
	/*for(int i=0;i<n;i++) {
        cout << dist[i] << " ";
	}
	cout << "\n";*/
}
int find_par(int x) {
	if(x==parent[x]) return x;
	int par=find_par(parent[x]);
	parent[x]=par;
	return par;
}
void spoji(int x,int y) {
	x=find_par(x);
	y=find_par(y);
	if(x==y) return;
	if(depth[x]==depth[y]) depth[x]+=1;
	if(depth[x]>depth[y]) parent[y]=x;
	else parent[x]=y;
}
void dfs(int x,int par,int d1) {
	parent2[x][0]=par;
	depth[x]=d1;
	//cout << x << " " << par << "\n";
	for(int i=0;i<v2[x].size();i++) {
		if(v2[x][i].first==par) continue;
		maxi[v2[x][i].first][0]=v2[x][i].second;
		//cout << v2[x][i].first << " " << maxi[v2[x][i].first][0] << "\n";
		dfs(v2[x][i].first,x,d1+1);
	}
}
llint lca(int a,int b) {
	if(depth[a]<depth[b]) swap(a,b);
	llint sol=0;
	for(int i=0;i<20;i++) {
		if((depth[a]-depth[b]) & (1 << i)) {
			sol=max(sol,maxi[a][i]);
			a=parent2[a][i];
		}
	}
	if(a==b) return sol;
	for(int i=19;i>=0;i--) {
		if(parent2[a][i]==parent2[b][i]) continue;
		sol=max(sol,max(maxi[a][i],maxi[b][i]));
		a=parent2[a][i];
		b=parent2[b][i];
	}
	return max(sol,max(maxi[a][0],maxi[b][0]));
}
int main()
{
	cin >> n >> m >> k >> q;
	//std::cout << "bok";
	for(int i=0;i<m;i++) {
		int a,b,w;
		cin >> a >> b >> w;
		v[a-1].push_back(make_pair(b-1,w));
		v[b-1].push_back(make_pair(a-1,w));
		e.push_back(make_pair(w,make_pair(a-1,b-1)));
	}
	dijkstra();
	for(int i=0;i<m;i++) {
		int x=e[i].second.first,y=e[i].second.second;
		if(ind[x]==ind[y]) continue;
		if(m1[make_pair(ind[x],ind[y])]==0 or dist[x]+e[i].first+dist[y]<m1[make_pair(ind[x],ind[y])]) {
			m1[make_pair(ind[x],ind[y])]=dist[x]+e[i].first+dist[y];
			m1[make_pair(ind[y],ind[x])]=dist[x]+e[i].first+dist[y];
		}
	}
	for(int i=0;i<m;i++) {
		int x=e[i].second.first,y=e[i].second.second;
		if(ind[x]==ind[y] or m1[make_pair(ind[x],ind[y])]==0) continue;
		e2.push_back(make_pair(m1[make_pair(ind[x],ind[y])],make_pair(ind[x],ind[y])));
		m1[make_pair(ind[x],ind[y])]=0;
		m1[make_pair(ind[y],ind[x])]=0;
	}
	sort(e2.begin(),e2.end());
	for(int i=0;i<k;i++) parent[i]=i;
	for(int i=0;i<e2.size();i++) {
		int x=e2[i].second.first,y=e2[i].second.second;
		if(find_par(x)==find_par(y)) continue;
		spoji(x,y);
		v2[x].push_back(make_pair(y,e2[i].first));
		v2[y].push_back(make_pair(x,e2[i].first));
		//cout << x << " " << y << " " << e2[i].first << "\n";
	}
	memset(depth,0,sizeof(depth));
	dfs(0,0,0);
	for(int i=1;i<20;i++) {
		for(int j=0;j<n;j++) {
			parent2[j][i]=parent2[parent2[j][i-1]][i-1];
			maxi[j][i]=max(maxi[parent2[j][i-1]][i-1],maxi[j][i-1]);
		}
	}
	//cout << maxi[1][0] << " " << maxi[2][0] << "\n";
	/*for(int i=0;i<n;i++) {
        cout << ind[i] << " ";
	}
	cout << "\n";*/
	for(int i=0;i<q;i++) {
		int a,b;
		cin >> a >> b;
		cout << lca(ind[a-1],ind[b-1]) << "\n";
	}
	return 0;
}


#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long int llint;
llint dist[100005];
int n,m,k,q,ind[100005],parent[100005],depth[100005],maxi[100005][25],parent2[100005][25];
vector <pair<int,int> > v[100005];
vector <pair<int,llint> > v2[100005];
set <pair<llint,int> > s;
map <pair<int,int>,llint> m1;
vector <pair<int,pair<int,int> > > e;
vector <pair<llint,pair<int,int> > > e2;
void dijkstra() {
	for(int i=0;i<n;i++) {
		dist[i]=1e18;
		if(i<k) {
            dist[i]=0;
            ind[i]=i;
		}
		s.insert(make_pair(dist[i],i));
	}
	while(!s.empty()) {
		llint d=(*s.begin()).first,x=(*s.begin()).second;
		s.erase(s.begin());
		for(int i=0;i<v[x].size();i++) {
			if(d+v[x][i].second<dist[v[x][i].first]) {
				ind[v[x][i].first]=ind[x];
				s.erase(make_pair(dist[v[x][i].first],v[x][i].first));
				dist[v[x][i].first]=d+v[x][i].second;
				s.insert(make_pair(dist[v[x][i].first],v[x][i].first));
			}
		}
        /*for(int i=0;i<n;i++) {
            cout << dist[i] << " ";
        }
        cout << "\n";*/
	}
	/*for(int i=0;i<n;i++) {
        cout << dist[i] << " ";
	}
	cout << "\n";*/
}
int find_par(int x) {
	if(x==parent[x]) return x;
	int par=find_par(parent[x]);
	parent[x]=par;
	return par;
}
void spoji(int x,int y) {
	x=find_par(x);
	y=find_par(y);
	if(x==y) return;
	if(depth[x]==depth[y]) depth[x]+=1;
	if(depth[x]>depth[y]) parent[y]=x;
	else parent[x]=y;
}
void dfs(int x,int par,int d1) {
	parent2[x][0]=par;
	depth[x]=d1;
	//cout << x << " " << par << "\n";
	for(int i=0;i<v2[x].size();i++) {
		if(v2[x][i].first==par) continue;
		maxi[v2[x][i].first][0]=v2[x][i].second;
		//cout << v2[x][i].first << " " << maxi[v2[x][i].first][0] << "\n";
		dfs(v2[x][i].first,x,d1+1);
	}
}
int lca(int a,int b) {
	if(depth[a]<depth[b]) swap(a,b);
	int sol=0;
	for(int i=0;i<20;i++) {
		if((depth[a]-depth[b]) & (1 << i)) {
			sol=max(sol,maxi[a][i]);
			a=parent2[a][i];
		}
	}
	if(a==b) return sol;
	for(int i=19;i>=0;i--) {
		if(parent2[a][i]==parent2[b][i]) continue;
		sol=max(sol,max(maxi[a][i],maxi[b][i]));
		a=parent2[a][i];
		b=parent2[b][i];
	}
	return max(sol,max(maxi[a][0],maxi[b][0]));
}
int main()
{
	cin >> n >> m >> k >> q;
	//std::cout << "bok";
	for(int i=0;i<m;i++) {
		int a,b,w;
		cin >> a >> b >> w;
		v[a-1].push_back(make_pair(b-1,w));
		v[b-1].push_back(make_pair(a-1,w));
		e.push_back(make_pair(w,make_pair(a-1,b-1)));
	}
	dijkstra();
	for(int i=0;i<m;i++) {
		int x=e[i].second.first,y=e[i].second.second;
		if(ind[x]==ind[y]) continue;
		if(m1[make_pair(ind[x],ind[y])]==0 or dist[x]+e[i].first+dist[y]<m1[make_pair(ind[x],ind[y])]) {
			m1[make_pair(ind[x],ind[y])]=dist[x]+e[i].first+dist[y];
			m1[make_pair(ind[y],ind[x])]=dist[x]+e[i].first+dist[y];
		}
	}
	for(int i=0;i<m;i++) {
		int x=e[i].second.first,y=e[i].second.second;
		if(ind[x]==ind[y] or m1[make_pair(ind[x],ind[y])]==0) continue;
		e2.push_back(make_pair(m1[make_pair(ind[x],ind[y])],make_pair(ind[x],ind[y])));
		m1[make_pair(ind[x],ind[y])]=0;
		m1[make_pair(ind[y],ind[x])]=0;
	}
	sort(e2.begin(),e2.end());
	for(int i=0;i<k;i++) parent[i]=i;
	for(int i=0;i<e2.size();i++) {
		int x=e2[i].second.first,y=e2[i].second.second;
		if(find_par(x)==find_par(y)) continue;
		spoji(x,y);
		v2[x].push_back(make_pair(y,e2[i].first));
		v2[y].push_back(make_pair(x,e2[i].first));
		//cout << x << " " << y << " " << e2[i].first << "\n";
	}
	memset(depth,0,sizeof(depth));
	dfs(0,0,0);
	for(int i=1;i<20;i++) {
		for(int j=0;j<n;j++) {
			parent2[j][i]=parent2[parent2[j][i-1]][i-1];
			maxi[j][i]=max(maxi[parent2[j][i-1]][i-1],maxi[j][i-1]);
		}
	}
	//cout << maxi[1][0] << " " << maxi[2][0] << "\n";
	/*for(int i=0;i<n;i++) {
        cout << ind[i] << " ";
	}
	cout << "\n";*/
	for(int i=0;i<q;i++) {
		int a,b;
		cin >> a >> b;
		cout << lca(ind[a-1],ind[b-1]) << "\n";
	}
	return 0;
}


#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long int llint;
llint dist[100005];
llint n,m,k,q,ind[100005],parent[100005],depth[100005],maxi[100005][25],parent2[100005][25];
vector <pair<int,int> > v[100005];
vector <pair<int,llint> > v2[100005];
set <pair<llint,int> > s;
map <pair<int,int>,llint> m1;
vector <pair<int,pair<int,int> > > e;
vector <pair<llint,pair<int,int> > > e2;
void dijkstra() {
	for(int i=0;i<n;i++) {
		dist[i]=1e18;
		if(i<k) {
            dist[i]=0;
            ind[i]=i;
		}
		s.insert(make_pair(dist[i],i));
	}
	while(!s.empty()) {
		llint d=(*s.begin()).first,x=(*s.begin()).second;
		s.erase(s.begin());
		for(int i=0;i<v[x].size();i++) {
			if(d+v[x][i].second<dist[v[x][i].first]) {
				ind[v[x][i].first]=ind[x];
				s.erase(make_pair(dist[v[x][i].first],v[x][i].first));
				dist[v[x][i].first]=d+v[x][i].second;
				s.insert(make_pair(dist[v[x][i].first],v[x][i].first));
			}
		}
        /*for(int i=0;i<n;i++) {
            cout << dist[i] << " ";
        }
        cout << "\n";*/
	}
	/*for(int i=0;i<n;i++) {
        cout << dist[i] << " ";
	}
	cout << "\n";*/
}
int find_par(int x) {
	if(x==parent[x]) return x;
	int par=find_par(parent[x]);
	parent[x]=par;
	return par;
}
void spoji(int x,int y) {
	x=find_par(x);
	y=find_par(y);
	if(x==y) return;
	if(depth[x]==depth[y]) depth[x]+=1;
	if(depth[x]>depth[y]) parent[y]=x;
	else parent[x]=y;
}
void dfs(int x,int par,int d1) {
	parent2[x][0]=par;
	depth[x]=d1;
	//cout << x << " " << par << "\n";
	for(int i=0;i<v2[x].size();i++) {
		if(v2[x][i].first==par) continue;
		maxi[v2[x][i].first][0]=v2[x][i].second;
		//cout << v2[x][i].first << " " << maxi[v2[x][i].first][0] << "\n";
		dfs(v2[x][i].first,x,d1+1);
	}
}
llint lca(int a,int b) {
	if(depth[a]<depth[b]) swap(a,b);
	llint sol=0;
	for(int i=0;i<20;i++) {
		if((depth[a]-depth[b]) & (1 << i)) {
			sol=max(sol,maxi[a][i]);
			a=parent2[a][i];
		}
	}
	if(a==b) return sol;
	for(int i=19;i>=0;i--) {
		if(parent2[a][i]==parent2[b][i]) continue;
		sol=max(sol,max(maxi[a][i],maxi[b][i]));
		a=parent2[a][i];
		b=parent2[b][i];
	}
	return max(sol,max(maxi[a][0],maxi[b][0]));
}
int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m >> k >> q;
	//std::cout << "bok";
	for(int i=0;i<m;i++) {
		int a,b,w;
		cin >> a >> b >> w;
		v[a-1].push_back(make_pair(b-1,w));
		v[b-1].push_back(make_pair(a-1,w));
		e.push_back(make_pair(w,make_pair(a-1,b-1)));
	}
	dijkstra();
	for(int i=0;i<m;i++) {
		int x=e[i].second.first,y=e[i].second.second;
		if(ind[x]==ind[y]) continue;
		if(m1[make_pair(ind[x],ind[y])]==0 or dist[x]+e[i].first+dist[y]<m1[make_pair(ind[x],ind[y])]) {
			m1[make_pair(ind[x],ind[y])]=dist[x]+e[i].first+dist[y];
			m1[make_pair(ind[y],ind[x])]=dist[x]+e[i].first+dist[y];
		}
	}
	for(int i=0;i<m;i++) {
		int x=e[i].second.first,y=e[i].second.second;
		if(ind[x]==ind[y] or m1[make_pair(ind[x],ind[y])]==0) continue;
		e2.push_back(make_pair(m1[make_pair(ind[x],ind[y])],make_pair(ind[x],ind[y])));
		m1[make_pair(ind[x],ind[y])]=0;
		m1[make_pair(ind[y],ind[x])]=0;
	}
	sort(e2.begin(),e2.end());
	for(int i=0;i<k;i++) parent[i]=i;
	for(int i=0;i<e2.size();i++) {
		int x=e2[i].second.first,y=e2[i].second.second;
		if(find_par(x)==find_par(y)) continue;
		spoji(x,y);
		v2[x].push_back(make_pair(y,e2[i].first));
		v2[y].push_back(make_pair(x,e2[i].first));
		//cout << x << " " << y << " " << e2[i].first << "\n";
	}
	memset(depth,0,sizeof(depth));
	dfs(0,0,0);
	for(int i=1;i<20;i++) {
		for(int j=0;j<n;j++) {
			parent2[j][i]=parent2[parent2[j][i-1]][i-1];
			maxi[j][i]=max(maxi[parent2[j][i-1]][i-1],maxi[j][i-1]);
		}
	}
	//cout << maxi[1][0] << " " << maxi[2][0] << "\n";
	/*for(int i=0;i<n;i++) {
        cout << ind[i] << " ";
	}
	cout << "\n";*/
	for(int i=0;i<q;i++) {
		int a,b;
		cin >> a >> b;
		cout << lca(ind[a-1],ind[b-1]) << "\n";
	}
	return 0;
}


#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long int llint;
llint dist[100005];
llint n,m,k,q,ind[100005],parent[100005],depth[100005],maxi[100005][25],parent2[100005][25],sol[300005];
vector <pair<int,int> > v[100005];
vector <pair<int,llint> > v2[100005];
set <pair<llint,int> > s;
map <pair<int,int>,llint> m1;
vector <pair<int,pair<int,int> > > e;
vector <pair<llint,pair<int,int> > > e2;
set <int> s1[100005];
void dijkstra() {
	for(int i=0;i<n;i++) {
		dist[i]=1e18;
		if(i<k) {
            dist[i]=0;
            ind[i]=i;
		}
		s.insert(make_pair(dist[i],i));
	}
	while(!s.empty()) {
		llint d=(*s.begin()).first,x=(*s.begin()).second;
		s.erase(s.begin());
		for(int i=0;i<v[x].size();i++) {
			if(d+v[x][i].second<dist[v[x][i].first]) {
				ind[v[x][i].first]=ind[x];
				s.erase(make_pair(dist[v[x][i].first],v[x][i].first));
				dist[v[x][i].first]=d+v[x][i].second;
				s.insert(make_pair(dist[v[x][i].first],v[x][i].first));
			}
		}
	}
}
int find_par(int x) {
	if(x==parent[x]) return x;
	int par=find_par(parent[x]);
	parent[x]=par;
	return par;
}
void spoji(int x,int y,int a) {
	x=find_par(x);
	y=find_par(y);
	if(x==y) return;
	if(depth[x]==depth[y]) depth[x]+=1;
	if(depth[x]>depth[y]) parent[y]=x;
	else parent[x]=y;
	if(s1[x].size()>s1[y].size()) {
		for(set <int>::iterator it=s1[y].begin();it!=s1[y].end();it++) {
			if(s1[x].find(*it)!=s1[x].end()) sol[*it]=a;
			s1[x].insert(*it);
		}
		s1[y].clear();
		if(x!=parent[y]) swap(s1[x],s1[y]);
	}
	else {
		for(set <int>::iterator it=s1[x].begin();it!=s1[x].end();it++) {
			if(s1[y].find(*it)!=s1[y].end()) sol[*it]=a;
			s1[y].insert(*it);
		}
		s1[x].clear();
		if(y!=parent[x]) swap(s1[x],s1[y]);
	}
}
int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m >> k >> q;
	for(int i=0;i<m;i++) {
		int a,b,w;
		cin >> a >> b >> w;
		v[a-1].push_back(make_pair(b-1,w));
		v[b-1].push_back(make_pair(a-1,w));
		e.push_back(make_pair(w,make_pair(a-1,b-1)));
	}
	dijkstra();
	for(int i=0;i<m;i++) {
		int x=e[i].second.first,y=e[i].second.second;
		if(ind[x]==ind[y]) continue;
		if(m1[make_pair(ind[x],ind[y])]==0 or dist[x]+e[i].first+dist[y]<m1[make_pair(ind[x],ind[y])]) {
			m1[make_pair(ind[x],ind[y])]=dist[x]+e[i].first+dist[y];
			m1[make_pair(ind[y],ind[x])]=dist[x]+e[i].first+dist[y];
		}
	}
	for(int i=0;i<m;i++) {
		int x=e[i].second.first,y=e[i].second.second;
		if(ind[x]==ind[y] or m1[make_pair(ind[x],ind[y])]==0) continue;
		e2.push_back(make_pair(m1[make_pair(ind[x],ind[y])],make_pair(ind[x],ind[y])));
		m1[make_pair(ind[x],ind[y])]=0;
		m1[make_pair(ind[y],ind[x])]=0;
	}
	sort(e2.begin(),e2.end());
	for(int i=0;i<k;i++) parent[i]=i;
	for(int i=0;i<q;i++) {
		int a,b;
		cin >> a >> b;
		s1[ind[a-1]].insert(i);
		s1[ind[b-1]].insert(i);
	}
	for(int i=0;i<e2.size();i++) {
		int x=e2[i].second.first,y=e2[i].second.second;
		if(find_par(x)==find_par(y)) continue;
		spoji(x,y,e2[i].first);
	}
	for(int i=0;i<q;i++) {
		cout << sol[i] << "\n";
	}
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define mp make_pair
#define pb push_back
#define ip pair<int,ll>
#define ff first
#define ss second
#define popcnt __builtin_popcount
#define MAX 200005
const ll MOD = 1000000007;
const ll INF = 1e18;

int parent[MAX];
int find_set(int v){
	if(parent[v] == v)
		return v;
	parent[v] = find_set(parent[v]);
	return parent[v];
}

int main(){
	ll n,m,k,q,w;
	cin>>n>>m>>k>>q;
	vector<ip> adj[n+1];

	for(int i=0;i<m;i++){
		int u,v;
		cin>>u>>v>>w;
		adj[u].pb({v,w});
		adj[v].pb({u,w});
	}

	vector<ll> d(n+1,INF);
	vector<int> prev(n+1,-1);

	priority_queue<ip,vector<ip>,greater<ip> > pq;
	for(int i=1;i<=k;i++){
		d[i] = 0;
		pq.push({0,i});
		prev[i] = i;
	}

	int cnt = 0;
	vector<int> vis(n+1,0);
	while(!pq.empty()){
		ip z = pq.top();
		int idx = z.ss;
		pq.pop();

		if(vis[idx])
			continue;

		vis[idx] = 1;
		++cnt;
		if(cnt == n)
			break;

		for(ip next: adj[idx]){
			if(!vis[next.ff] && z.ff + next.ss < d[next.ff]){
				d[next.ff] = z.ff + next.ss;
				prev[next.ff] = prev[idx];
				pq.push({d[next.ff],next.ff});
			}
		}
	}

	vector<pair<ll,pair<int,int> > > dist;

	for(int u=1;u<=n;u++){
		for(ip z: adj[u]){
			if(prev[u] != prev[z.ff]){
				dist.pb({z.ss+d[u]+d[z.ff],{prev[u],prev[z.ff]}});
			}
		}
	}

	sort(dist.begin(),dist.end());

	// cout<<"Dist:\n";
	// for(int i=0;i<dist.size();i++){
	// 	cout<< dist[i].ff << " " << dist[i].ss.ff << " " << dist[i].ss.ss << "\n";
	// }

	for(int i=1;i<=2*k;i++)
		parent[i] = i;

	ll res[2*k+1];
	ll up[2*k+1];
	int cur = k+1;
	for(int i=0;i<dist.size();i++){
		ll val = dist[i].ff;
		int u = find_set(dist[i].ss.ff);
		int v = find_set(dist[i].ss.ss);
		if(u == v)
			continue;
		parent[u] = parent[v] = cur;
		up[u] = up[v] = cur;
		res[cur] = val;
		++cur;
	}

	int f[cur][20];
	memset(f,0,sizeof(f));

	int dep[cur];
	dep[cur-1] = 0;

	for(int i=cur-2;i>=1;i--){
		dep[i] = dep[up[i]]+1;
		f[i][0] = up[i];
		for(int j=1;j<20;j++)
			f[i][j] = f[f[i][j-1]][j-1];
	}

	// for(int i=1;i<cur;i++){
	// 	cout<<"i="<<i<<": ";
	// 	for(int j=0;j<10;j++){
	// 		cout<<f[i][j]<<" ";
	// 	}
	// 	cout<<"\n";
	// }

	for(int i=0;i<q;i++){
		int a,b;
		cin>>a>>b;

		if(dep[a] > dep[b])
			swap(a,b);

		for(int j=19;j>=0;j--){
			if(dep[b]-dep[a] >= (1<<j))
				b = f[b][j];
		}

		for(int j=19;j>=0;j--){
			if(f[a][j] != f[b][j]){
				a = f[a][j];
				b = f[b][j];
			}
		}

		// cout<<"lca="<<f[a][0]<<"\n";

		cout<< res[f[a][0]] << "\n";
	}
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define mp make_pair
#define pb push_back
#define ip pair<ll,ll>
#define ff first
#define ss second
#define popcnt __builtin_popcount
#define MAX 200005
const ll MOD = 1000000007;
const ll INF = 1e18;

int parent[MAX];
int find_set(int v){
	if(parent[v] == v)
		return v;
	parent[v] = find_set(parent[v]);
	return parent[v];
}

int main(){
	ll n,m,k,q,w;
	cin>>n>>m>>k>>q;
	vector<ip> adj[n+1];

	for(int i=0;i<m;i++){
		int u,v;
		cin>>u>>v>>w;
		adj[u].pb({v,w});
		adj[v].pb({u,w});
	}

	vector<ll> d(n+1,INF);
	vector<int> prev(n+1,-1);

	priority_queue<ip,vector<ip>,greater<ip> > pq;
	for(int i=1;i<=k;i++){
		d[i] = 0;
		pq.push({0,i});
		prev[i] = i;
	}

	int cnt = 0;
	vector<int> vis(n+1,0);
	while(!pq.empty()){
		ip z = pq.top();
		int idx = z.ss;
		pq.pop();

		if(vis[idx])
			continue;

		vis[idx] = 1;
		++cnt;
		if(cnt == n)
			break;

		for(ip next: adj[idx]){
			if(!vis[next.ff] && z.ff + next.ss < d[next.ff]){
				d[next.ff] = z.ff + next.ss;
				prev[next.ff] = prev[idx];
				pq.push({d[next.ff],next.ff});
			}
		}
	}

	vector<pair<ll,ip > > dist;

	for(int u=1;u<=n;u++){
		for(ip z: adj[u]){
			if(prev[u] != prev[z.ff]){
				dist.pb({z.ss+d[u]+d[z.ff],{prev[u],prev[z.ff]}});
			}
		}
	}

	sort(dist.begin(),dist.end());

	// cout<<"Dist:\n";
	// for(int i=0;i<dist.size();i++){
	// 	cout<< dist[i].ff << " " << dist[i].ss.ff << " " << dist[i].ss.ss << "\n";
	// }

	for(int i=1;i<=2*k;i++)
		parent[i] = i;

	ll res[2*k+1];
	ll up[2*k+1];
	int cur = k+1;
	for(int i=0;i<dist.size();i++){
		ll val = dist[i].ff;
		int u = find_set(dist[i].ss.ff);
		int v = find_set(dist[i].ss.ss);
		if(u == v)
			continue;
		parent[u] = parent[v] = cur;
		up[u] = up[v] = cur;
		res[cur] = val;
		++cur;
	}

	int f[cur][20];
	memset(f,0,sizeof(f));

	int dep[cur];
	dep[cur-1] = 0;

	for(int i=cur-2;i>=1;i--){
		dep[i] = dep[up[i]]+1;
		f[i][0] = up[i];
		for(int j=1;j<20;j++)
			f[i][j] = f[f[i][j-1]][j-1];
	}

	// for(int i=1;i<cur;i++){
	// 	cout<<"i="<<i<<": ";
	// 	for(int j=0;j<10;j++){
	// 		cout<<f[i][j]<<" ";
	// 	}
	// 	cout<<"\n";
	// }

	for(int i=0;i<q;i++){
		int a,b;
		cin>>a>>b;

		if(dep[a] > dep[b])
			swap(a,b);

		for(int j=19;j>=0;j--){
			if(dep[b]-dep[a] >= (1<<j))
				b = f[b][j];
		}

		for(int j=19;j>=0;j--){
			if(f[a][j] != f[b][j]){
				a = f[a][j];
				b = f[b][j];
			}
		}

		// cout<<"lca="<<f[a][0]<<"\n";

		cout<< res[f[a][0]] << "\n";
	}
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define mp make_pair
#define pb push_back
#define ip pair<ll,ll>
#define ff first
#define ss second
#define popcnt __builtin_popcount
#define MAX 200005
const ll MOD = 1000000007;
const ll INF = 1e18;

int parent[MAX],r[MAX],head[MAX];
int find_set(int v){
	if(parent[v] == v)
		return v;
	parent[v] = find_set(parent[v]);
	return parent[v];
}

void union_set(int u, int v, int h){
	if(r[u] > r[v])
		swap(u,v);
	parent[u] = v;
	if(r[u] == r[v])
		++r[v];
	head[v] = h;
}

int main(){
	ios_base::sync_with_stdio(0); cin.tie(0);

	ll n,m,k,q,w;
	cin>>n>>m>>k>>q;
	vector<ip> adj[n+1];

	for(int i=0;i<m;i++){
		int u,v;
		cin>>u>>v>>w;
		adj[u].pb({v,w});
		adj[v].pb({u,w});
	}

	vector<ll> d(n+1,INF);
	vector<int> prev(n+1,-1);

	priority_queue<ip,vector<ip>,greater<ip> > pq;
	for(int i=1;i<=k;i++){
		d[i] = 0;
		pq.push({0,i});
		prev[i] = i;
	}

	int cnt = 0;
	vector<int> vis(n+1,0);
	while(!pq.empty()){
		ip z = pq.top();
		int idx = z.ss;
		pq.pop();

		if(vis[idx])
			continue;

		vis[idx] = 1;
		++cnt;
		if(cnt == n)
			break;

		for(ip next: adj[idx]){
			if(!vis[next.ff] && z.ff + next.ss < d[next.ff]){
				d[next.ff] = z.ff + next.ss;
				prev[next.ff] = prev[idx];
				pq.push({d[next.ff],next.ff});
			}
		}
	}

	vector<pair<ll,pair<int,int> > > dist;

	for(int u=1;u<=n;u++){
		for(ip z: adj[u]){
			if(prev[u] != prev[z.ff]){
				dist.pb({z.ss+d[u]+d[z.ff],{prev[u],prev[z.ff]}});
			}
		}
	}

	sort(dist.begin(),dist.end());

	// cout<<"Dist:\n";
	// for(int i=0;i<dist.size();i++){
	// 	cout<< dist[i].ff << " " << dist[i].ss.ff << " " << dist[i].ss.ss << "\n";
	// }

	for(int i=1;i<=2*k;i++){
		parent[i] = i;
		r[i] = 0;
		head[i] = i;
	}

	ll res[2*k+1];
	ll up[2*k+1];
	int cur = k+1;
	for(int i=0;i<dist.size();i++){
		ll val = dist[i].ff;
		int u = find_set(dist[i].ss.ff);
		int v = find_set(dist[i].ss.ss);
		if(u == v)
			continue;
		up[head[u]] = up[head[v]] = cur;
		union_set(u,v,cur);
		res[cur] = val;
		++cur;
	}

	int f[cur][20];
	memset(f,0,sizeof(f));

	int dep[cur];
	dep[cur-1] = 0;

	for(int i=cur-2;i>=1;i--){
		dep[i] = dep[up[i]]+1;
		f[i][0] = up[i];
		for(int j=1;j<20;j++)
			f[i][j] = f[f[i][j-1]][j-1];
	}

	// for(int i=1;i<cur;i++){
	// 	cout<<"i="<<i<<": ";
	// 	for(int j=0;j<10;j++){
	// 		cout<<f[i][j]<<" ";
	// 	}
	// 	cout<<"\n";
	// }

	for(int i=0;i<q;i++){
		int a,b;
		cin>>a>>b;

		if(dep[a] > dep[b])
			swap(a,b);

		for(int j=19;j>=0;j--){
			if(dep[b]-dep[a] >= (1<<j))
				b = f[b][j];
		}

		for(int j=19;j>=0;j--){
			if(f[a][j] != f[b][j]){
				a = f[a][j];
				b = f[b][j];
			}
		}

		// cout<<"lca="<<f[a][0]<<"\n";

		cout<< res[f[a][0]] << "\n";
	}
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define mp make_pair
#define pb push_back
#define ip pair<ll,ll>
#define ff first
#define ss second
#define popcnt __builtin_popcount
#define MAX 200005
const ll MOD = 1000000007;
const ll INF = 1e18;

int parent[MAX],r[MAX],head[MAX];
int find_set(int v){
	if(parent[v] == v)
		return v;
	parent[v] = find_set(parent[v]);
	return parent[v];
}

void union_set(int u, int v, int h){
	if(r[u] > r[v])
		swap(u,v);
	parent[u] = v;
	if(r[u] == r[v])
		++r[v];
	head[v] = h;
}

int main(){
	ll n,m,k,q,w;
	cin>>n>>m>>k>>q;
	vector<ip> adj[n+1];

	for(int i=0;i<m;i++){
		int u,v;
		cin>>u>>v>>w;
		adj[u].pb({v,w});
		adj[v].pb({u,w});
	}

	vector<ll> d(n+1,INF);
	vector<int> prev(n+1,-1);

	priority_queue<ip,vector<ip>,greater<ip> > pq;
	for(int i=1;i<=k;i++){
		d[i] = 0;
		pq.push({0,i});
		prev[i] = i;
	}

	int cnt = 0;
	vector<int> vis(n+1,0);
	while(!pq.empty()){
		ip z = pq.top();
		int idx = z.ss;
		pq.pop();

		if(vis[idx])
			continue;

		vis[idx] = 1;
		++cnt;
		if(cnt == n)
			break;

		for(ip next: adj[idx]){
			if(!vis[next.ff] && z.ff + next.ss < d[next.ff]){
				d[next.ff] = z.ff + next.ss;
				prev[next.ff] = prev[idx];
				pq.push({d[next.ff],next.ff});
			}
		}
	}

	vector<pair<ll,pair<int,int> > > dist;

	for(int u=1;u<=n;u++){
		for(ip z: adj[u]){
			if(prev[u] != prev[z.ff]){
				dist.pb({z.ss+d[u]+d[z.ff],{prev[u],prev[z.ff]}});
			}
		}
	}

	sort(dist.begin(),dist.end());

	// cout<<"Dist:\n";
	// for(int i=0;i<dist.size();i++){
	// 	cout<< dist[i].ff << " " << dist[i].ss.ff << " " << dist[i].ss.ss << "\n";
	// }

	for(int i=1;i<=2*k;i++){
		parent[i] = i;
		r[i] = 0;
		head[i] = i;
	}

	ll res[2*k+1];
	ll up[2*k+1];
	int cur = k+1;
	for(int i=0;i<dist.size();i++){
		ll val = dist[i].ff;
		int u = find_set(dist[i].ss.ff);
		int v = find_set(dist[i].ss.ss);
		if(u == v)
			continue;
		up[head[u]] = up[head[v]] = cur;
		union_set(u,v,cur);
		res[cur] = val;
		++cur;
	}

	int f[cur][20];
	memset(f,0,sizeof(f));

	int dep[cur];
	dep[cur-1] = 0;

	for(int i=cur-2;i>=1;i--){
		dep[i] = dep[up[i]]+1;
		f[i][0] = up[i];
		for(int j=1;j<20;j++)
			f[i][j] = f[f[i][j-1]][j-1];
	}

	// for(int i=1;i<cur;i++){
	// 	cout<<"i="<<i<<": ";
	// 	for(int j=0;j<10;j++){
	// 		cout<<f[i][j]<<" ";
	// 	}
	// 	cout<<"\n";
	// }

	for(int i=0;i<q;i++){
		int a,b;
		cin>>a>>b;

		if(dep[a] > dep[b])
			swap(a,b);

		for(int j=19;j>=0;j--){
			if(dep[b]-dep[a] >= (1<<j))
				b = f[b][j];
		}

		for(int j=19;j>=0;j--){
			if(f[a][j] != f[b][j]){
				a = f[a][j];
				b = f[b][j];
			}
		}

		// cout<<"lca="<<f[a][0]<<"\n";

		cout<< res[f[a][0]] << "\n";
	}
}