program kruskal;
const maxn=105;
type node=record
fromv,endv,data:integer;
end;
arr=array[1..maxn] of integer;
jilu=array[1..maxn*maxn] of node;
var father:array[1..maxn] of integer;
elist:jilu;
c:array[1..maxn] of integer;
i,j,t,x,y,n,d,t1,num,ans:integer;
procedure swap(var a,b:node);
var temp:node;
begin
temp:=a;a:=b;b:=temp;
end;
procedure sort(var a:jilu;l,r:integer);
var i,j,mid,k:integer;
begin
if l>=r then exit;
i:=l;
mid:=a[(l+r) div 2].data;
for k:=l to r do
begin
if a[k].data <= mid
then
begin
swap(a[i],a[k]);
inc(i);
end;
end;
j:=i;
dec(i);
while (i>=l)and (a[i].data=mid) do
dec(i);
while (j<=r) and (a[j].data=mid) do
inc(j);
sort(a,l,i-1);
sort(a,j,r);
end;
function find(i:integer):integer;
begin
if i=father[i] then exit(i);
father[i]:=find(father[i]);
exit(father[i]);
end;
procedure unit1(a,b:integer);
var a1,a2:integer;
begin
a1:=find(a);a2:=find(b);
if a1<>a2 then
father[a1]:=a2;
end;
function judge(a,b:integer):boolean;
var a1,a2:integer;
begin
a1:=find(a);
a2:=find(b);
exit(a1=a2);
end;
procedure sort1();
var i,j,t:integer;
begin
for i:=1 to num do
begin
t:=i;
for j:=i+1 to num do
if elist[t].data>elist[j].data then t:=j;
if t<>i then swap(elist[t],elist[i]);
end;
end;
begin
//sort(father,1,8);
//assign(input,'aaa.txt');
//reset(input);
while(true) do
begin
readln(n);
for i:=1 to n do father[i]:=i;
if(n=0) then break;
num:=0;
for i:=1 to n*(n-1) div 2 do
begin
readln(x,y,d,t);
if t=1 then
unit1(x,y)
else
begin
inc(num);
elist[num].fromv:=x;
elist[num].endv:=y;
elist[num].data:=d;
end;
end;
sort1;
ans:=0;
for i:=1 to num do
begin
if not(judge(elist[i].fromv,elist[i].endv)) then
begin
inc(ans,elist[i].data);
unit1(elist[i].fromv,elist[i].endv);
end;
end;
writeln(ans);
end;
end.
/**************************************************************
Problem: 2205
User: admin
Language: Pascal
Result: Wrong Answer
****************************************************************/