//并查集+krustal,如果已经修建道路则直接将两个点合并
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int father[101];
struct Edge;
vector<Edge>Edge_list;
void initConfig()
{
for (int i = 0; i < 101; i++)
{
father[i] = i;
}
Edge_list.clear();
}
int findFather(int x)
{
if (x == father[x])
{
return x;
}
else
{
father[x] = findFather(father[x]);
return father[x];
}
}
void unionFather(int x, int y)
{
int x_father = findFather(x);
int y_father = findFather(y);
father[y_father] = father[x_father];
}
struct Edge
{
int U, V, WEIGHT;
Edge(int a, int b, int c)
{
U = a; V = b; WEIGHT = c;
}
};
bool cmp(Edge a, Edge b)
{
return a.WEIGHT < b.WEIGHT;
}
int krustal(int N_nodes, int union_count)
{
sort(Edge_list.begin(), Edge_list.end(), cmp);
int sum = 0;
int count = 0;
for (int i = 0; i < Edge_list.size(); i++)
{
Edge e = Edge_list[i];
if (findFather(e.U) != findFather(e.V))
{
sum = sum + e.WEIGHT;
unionFather(e.U, e.V);
count++;
}
if (count == N_nodes - 1 - union_count)
{
break;
}
}
return sum;
}
int main()
{
int N;
while (scanf("%d", &N) != EOF)
{
if (N == 0)
{
break;
}
initConfig();
int union_count = 0;
for (int i = 0; i < N * (N - 1) / 2; i++)
{
int U, V, weight, conection;
scanf("%d %d %d %d", &U, &V, &weight, &conection);
if (conection == 0)
{
Edge_list.push_back(Edge(U, V, weight));
//Edge_list.push_back(Edge(V, U, weight));
}
else
{
unionFather(U, V);
union_count++;
}
}
int sum = krustal(N, union_count);
cout << sum << endl;
}
}