//自己真的是。。。。哎。。。
//思想上的问题,只要认为已经修建的成本看为0就可以了
//其他的和最小生成树的模板没什么区别
//
#include<iostream>
#include<stdio.h>
using namespace std;
const int MAX=9999999;
int map[101][101];
int n,flag[101][101],visit[101],low[101],flag1;
int prim()
{
memset(visit,0,sizeof(visit));
int i,j,result=0,pos,m=0;
visit[1]=1;
pos=1;
for(i=1;i<=n;i++)
{
if(i!=pos)
low[i]=map[pos][i];
}
for(i=1;i<n;i++)
{
int min=MAX;
for(j=1;j<=n;j++)
{
if(visit[j]==0&&min>low[j])
{
min=low[j];
pos=j;
}
}
if(min!=MAX)
result+=min;
//if(
// cout<<result<<" ";
visit[pos]=1;
for(j=1;j<=n;j++)
{
if(visit[j]==0&&low[j]>map[pos][j])
{
low[j]=map[pos][j];
}
}
}
return result;
}
int main()
{
while(cin>>n,n)
{
memset(flag,0,sizeof(flag));
int m=n*(n-1)/2,i,j;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
map[i][j]=MAX;
}
}
int a,b,c,d;
while(m--)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
map[a][b]=c;
map[b][a]=c;
if(d==1)
{
map[a][b]=0;
map[b][a]=0;
//flag[a][b]=1;
// flag[b][a]=1;
}
}
//for(i=1;i<=n;i++)
//cout<<flag[i]<<" ";
int ans=prim();
printf("%d\n",ans);
}
}