#include <iostream>
#include <fstream>
#include <vector>
#include <utility>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
struct Muchie
{
int n1, n2, cost, per;
Muchie(int n1, int n2, int cost, int per)
:n1(n1)
,n2(n2)
,cost(cost)
,per(per)
{}
};
bool comparison_function(Muchie m1, Muchie m2)
{
if(m1.cost < m2.cost)
return true;
if(m1.cost == m2.cost)
if(m1.per < m2.per)
return true;
return false;
}
int Find_set(int v1, vector<pair<int, int> > & arb)
{
//gasirea componentei conexe in care se afla v1
//daca v1 e chiar reprezentantul componentei conexe
if(arb[v1].first == v1)
return v1;
//altfel urcand la parintele lui v1 determinam reprezentantul
//si folosim Compresia caii, pentru ca la pasul urmator
//sa determinam reprezentantul in O(1)
arb[v1].first = Find_set(arb[v1].first, arb);
return arb[v1].first;
}
void Union(int v1, int v2, vector<pair<int, int> > & arb)
{
//uniunea a doua componente conexe
//folosind Uniunea dupa rank
int p1 = Find_set(v1, arb);
int p2 = Find_set(v2, arb);
//daca primul are o inaltime mai mare
if(arb[p1].second > arb[p2].second)
arb[p2].first = p1;
else
{
arb[p1].first = p2;
//daca ambii sunt egali ca inaltime
//cresc inaltimea lui p2
if(arb[p1].second == arb[p2].second)
arb[p2].second++;
}
}
vector<Muchie> Kruskal(int N, int M, vector<Muchie> muchii, long long & cost_min)
{
//implementarea algoritmului lui Kruskal
vector<pair<int, int> > arb;// vectorul de parinti cu inaltimi
vector< Muchie > ama;
for(int i = 0; i <= N; i++)
arb.push_back(std::make_pair(i, 0));
sort(muchii.begin(), muchii.end(), comparison_function);
for(size_t i = 0; i < muchii.size(); i++)
{
if((int) ama.size() == N - 1 )
break;// am gasit AMA
if(Find_set(muchii[i].n1, arb) != Find_set(muchii[i].n2, arb))
{
ama.push_back(muchii[i]);
cost_min += muchii[i].cost;
Union(muchii[i].n1, muchii[i].n2, arb);
}
}
return ama;
}
bool f(Muchie m1, Muchie m2)
{
return m1.per > m2.per;
}
int main()
{
ifstream inf("politie.in");
ofstream outf("politie.out");
int N, M, D, x, y, w, pre, P;
long long cost_min = 0, cost_querry;
vector<Muchie> v_muchii, ama;
inf >> N >> M >> D >> P;
for(int i = 0; i < M; i++)
{
inf >> x >> y >> w >> pre;
v_muchii.push_back( Muchie(x, y, w, pre) );
}
ama = Kruskal(N, M, v_muchii, cost_min);
sort(ama.begin(), ama.end(), f);
pre = -1;
for(int i = 0; i < ama.size(); i++)
{
if(P == 0)
break;
else
{
if(pre != ama[i].per)
{
outf<<ama[i].per<<"\n";
pre = ama[i].per;
P--;
}
}
}
inf.close();
outf.close();
return 0;
}