100 lines
2.5 KiB
C++
100 lines
2.5 KiB
C++
#include <algorithm>
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
#include <iostream>
|
|
using namespace std;
|
|
template <typename T>
|
|
void MergeSort(T *beg, T *end, bool (*cmp)(const T &, const T &)) {
|
|
if (end - beg <= 1) return;
|
|
size_t len = end - beg;
|
|
T *mid = beg + (len >> 1);
|
|
MergeSort(beg, mid, cmp);
|
|
MergeSort(mid, end, cmp);
|
|
T *tmp = new T[len];
|
|
T *cur_tmp = tmp, *cur_L = beg, *cur_R = mid;
|
|
while ((cur_L < mid) && (cur_R < end)) {
|
|
if (cmp(*cur_L, *cur_R))
|
|
*(cur_tmp++) = *(cur_L++);
|
|
else
|
|
*(cur_tmp++) = *(cur_R++);
|
|
}
|
|
while (cur_L < mid) *(cur_tmp++) = *(cur_L++);
|
|
while (cur_R < end) *(cur_tmp++) = *(cur_R++);
|
|
cur_tmp = tmp;
|
|
T *cur_dst = beg;
|
|
while (cur_dst < end) *(cur_dst++) = *(cur_tmp++);
|
|
delete[] tmp;
|
|
}
|
|
typedef long long LL;
|
|
typedef long double LDB;
|
|
const int kMaxN = 5e4 + 10;
|
|
const int kMaxM = 1e5 + 10;
|
|
int n, m, K;
|
|
struct Edge {
|
|
int u, v, w;
|
|
bool is_white;
|
|
} edge[kMaxM];
|
|
int penalty_for_white;
|
|
bool Cmp(const Edge &A, const Edge &B) {
|
|
int wa = (A.is_white ? A.w + penalty_for_white : A.w);
|
|
int wb = (B.is_white ? B.w + penalty_for_white : B.w);
|
|
if (wa == wb) return (int)A.is_white > (int)B.is_white;
|
|
return wa < wb;
|
|
}
|
|
int fa[kMaxN];
|
|
inline int ff(int u) {
|
|
int x = u, y;
|
|
while (fa[u] != u) u = fa[u];
|
|
while (x != u) {
|
|
y = fa[x];
|
|
fa[x] = u;
|
|
x = y;
|
|
}
|
|
return u;
|
|
}
|
|
void Calc(LL &res, int &white_used_count) {
|
|
white_used_count = 0;
|
|
res = 0;
|
|
MergeSort(edge, edge + m, Cmp);
|
|
for (int i = 0; i <= n; i++) fa[i] = i;
|
|
for (int i = 0; i < m; i++) {
|
|
int u = edge[i].u;
|
|
int v = edge[i].v;
|
|
int w = edge[i].is_white ? edge[i].w + penalty_for_white : edge[i].w;
|
|
if (ff(u) == ff(v)) continue;
|
|
fa[ff(u)] = ff(v);
|
|
if (edge[i].is_white) white_used_count++;
|
|
res += w;
|
|
}
|
|
}
|
|
int main() {
|
|
#ifdef local
|
|
freopen("pro.in", "r", stdin);
|
|
#endif
|
|
scanf("%d%d%d", &n, &m, &K);
|
|
for (int i = 0; i < m; i++) {
|
|
int u, v, w, col;
|
|
scanf("%d%d%d%d", &u, &v, &w, &col);
|
|
edge[i] = Edge{u, v, w, bool(col == 0)};
|
|
}
|
|
int L = -110, R = 110;
|
|
LL ans = 0x3f3f3f3f3f3f3f3f;
|
|
while (L < R) {
|
|
int M = (L + R) >> 1;
|
|
penalty_for_white = M;
|
|
LL res;
|
|
int white_used_count;
|
|
Calc(res, white_used_count);
|
|
// printf("mid=%d flag=%d\n",M,int(white_used_count >= K));
|
|
if (white_used_count >= K) {
|
|
ans = res - K * (LL)penalty_for_white;
|
|
// printf("ans=%lld mid=%d\n",ans,M);
|
|
L = M + 1;
|
|
} else if (white_used_count < K) {
|
|
R = M;
|
|
}
|
|
}
|
|
if (0x3f3f3f3f3f3f3f3f == ans) ans = -1;
|
|
printf("%lld\n", ans);
|
|
return 0;
|
|
} |