#include <bits/stdc++.h>
#define int long long
#define min(x,y) (((x)<(y))?(x):(y))
#define max(x,y) (((x)>(y))?(x):(y))
#define lowbit(x) ((x)&-(x))
#define abs(x) (((x)<(0))?(-(x)):(x))
#define swap(a,b) a^=b^=a^=b
#define INF 1e18
#define repeat(x) ((x)*((x)-1)/2)
#define MAXN 400005
using namespace std;
int n, m1, m2, k, min2id, now1id, now2id, ans, fa1[MAXN], fa2[MAXN], sz1[MAXN], sz2[MAXN], merge_from[MAXN], merge_to[MAXN], now_connect;
map<int, int> t[MAXN];
vector<int> nodes[MAXN], merge_node[MAXN];
struct edge
{
int u, v, w;
} e1[MAXN], e2[MAXN];
bool cmpw(edge x, edge y)
{
return x.w < y.w;
}
int getfa1(int id)
{
return ((fa1[id] == id) ? id : (fa1[id] = getfa1(fa1[id])));
}
int getfa2(int id)
{
return ((fa2[id] == id) ? id : getfa2(fa2[id]));
}
void print()
{
cout << "now_connect = " << now_connect << endl;
cout << "now1id = " << now1id << endl;
cout << "min2id = " << min2id << endl;
cout << "now2id = " << now2id << endl;
cout << "ans = " << ans << endl;
cout << "fa1:";
for (int i = 1; i <= n; i++)
{
cout << " " << fa1[i];
}
cout << endl;
cout << "sz1:";
for (int i = 1; i <= n; i++)
{
cout << " " << sz1[i];
}
cout << endl;
cout << "fa2:";
for (int i = 1; i <= n; i++)
{
cout << " " << fa2[i];
}
cout << endl;
cout << "sz2:";
for (int i = 1; i <= n; i++)
{
cout << " " << sz2[i];
}
cout << endl;
for (int i = 1; i <= n; i++)
{
cout << i << " (" << nodes[i].size() << ") :";
for (int j : nodes[i])
{
cout << " " << j;
}
cout << endl;
}
for (int i = 1; i <= n; i++)
{
for (pair<int, int> j : t[i])
{
cout << i << " " << j.first << " " << j.second << endl;
}
}
cout << endl;
}
signed main()
{
cin >> n >> m1 >> m2 >> k;
if (k == 0)
{
cout << 0;
return 0;
}
for (int i = 1; i <= m1; i++)
{
cin >> e1[i].u >> e1[i].v >> e1[i].w;
}
for (int i = 1; i <= m2; i++)
{
cin >> e2[i].u >> e2[i].v >> e2[i].w;
}
sort(e1 + 1, e1 + m1 + 1, cmpw);
sort(e2 + 1, e2 + m2 + 1, cmpw);
e2[m2 + 1].w = ans = 1000000000000000ll;
min2id = m2 + 1;
now2id = m2;
for (int i = 1; i <= n; i++)
{
fa1[i] = fa2[i] = i;
sz1[i] = sz2[i] = 1;
nodes[i].push_back(i);
}
for (int i = 1; i <= m2; i++)
{
int x = getfa2(e2[i].u);
int y = getfa2(e2[i].v);
if (x == y)
{
continue;
}
now_connect += sz2[x] * sz2[y];
if (sz2[x] < sz2[y])
{
fa2[x] = y;
sz2[y] += sz2[x];
merge_from[i] = x;
merge_to[i] = y;
for (int j : nodes[x])
{
nodes[y].push_back(j);
merge_node[i].push_back(j);
}
nodes[x].clear();
}
else
{
fa2[y] = x;
sz2[x] += sz2[y];
merge_from[i] = y;
merge_to[i] = x;
for (int j : nodes[y])
{
nodes[x].push_back(j);
merge_node[i].push_back(j);
}
nodes[y].clear();
}
if (now_connect >= k)
{
ans = e2[i].w;
now2id = min2id = i;
break;
}
}
for (int i = 1; i <= n; i++)
{
t[i][getfa2(i)]++;
}
for (now1id = 1; now1id <= m1; now1id++)
{
int x = getfa1(e1[now1id].u);
int y = getfa1(e1[now1id].v);
if (x == y)
{
continue;
}
now_connect += sz1[x] * sz1[y];
for (pair<int, int> i : t[y])
{
now_connect += repeat(i.second);
now_connect += repeat(t[x][i.first]);
t[x][i.first] += i.second;
now_connect -= repeat(t[x][i.first]);
}
t[y].clear();
fa1[y] = x;
sz1[x] += sz1[y];
if (now_connect >= k)
{
min2id = now2id;
ans = min(ans, e2[min2id].w + e1[now1id].w);
}
while (now2id >= 1 && now_connect >= k)
{
if (merge_node[now2id].size() == 0)
{
now2id--;
if (now_connect >= k)
{
min2id = now2id;
ans = min(ans, e2[min2id].w + e1[now1id].w);
}
continue;
}
int mf = merge_from[now2id];
int mt = merge_to[now2id];
fa2[mf] = mf;
sz2[mt] -= sz2[mf];
now_connect -= sz2[mt] * sz2[mf];
for (int i = 1; i <= sz2[mf]; i++)
{
nodes[mt].pop_back();
}
nodes[mf] = merge_node[now2id];
for (int i : nodes[mf])
{
int fai = getfa1(i);
now_connect += repeat(t[fai][mt]);
t[fai][mt]--;
now_connect -= repeat(t[fai][mt]);
now_connect += repeat(t[fai][mf]);
t[fai][mf]++;
now_connect -= repeat(t[fai][mf]);
if (t[fai][mt] == 0)
{
t[fai].erase(mt);
}
}
now2id--;
if (now_connect >= k)
{
min2id = now2id;
ans = min(ans, e2[min2id].w + e1[now1id].w);
}
}
}
if (ans >= 1000000000000000ll)
{
cout << -1;
return 0;
}
cout << ans;
return 0;
}