文件目录

// kruskal 贪心思想 并查集
#include <bits/stdc++.h>
using namespace std;
// 将所有边按照权重从小到大排序
// 遍历所有边,如果两点可以合并,进入mst(最小生成树)集
int n, m, p, u, v, w, t = 0, ans = 0;
struct edge
{
    int p, u, v, w;
    bool operator<(const edge &b) const
    {
        if (p == b.p)
            return w < b.w;
        return p < b.p;
    }
} e[10050];
int fat[2005];
void init()
{
    for (int i = 0; i < 2005; i++)
        fat[i] = i;
}
int findfat(int x)
{
    if (fat[x] != x)
        fat[x] = findfat(fat[x]); // 路径压缩
    return fat[x];
}
void uset(int a, int b)
{
    int fa = findfat(a);
    int fb = findfat(b);
    if (fa != fb)
        fat[fb] = fa;
}
void kruskal()
{
    sort(e, e + t);
    int nn = 0;
    for (int i = 0; i < t; i++)
    {
        int u = e[i].u, v = e[i].v;
        if (e[i].p == 1 || findfat(u) != findfat(v))
        {
            uset(u, v);
            ans += e[i].w;
            // cout<<e[i].w<<" ";
            nn++;
        }
    }
}
int main()
{
    cin >> n >> m;
    while (m--)
    {
        cin >> p >> u >> v >> w;
        e[t++] = {p, u, v, w};
    }
    init();
    kruskal();
    cout << ans;
    return 0;
}