#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int N = 1000+5;
struct Edge{
int u, v, dist;
Edge(){
u = 0;
v = 0;
dist = 0;
};
Edge(int a, int b, int c){
u = a;
v = b;
dist = c;
}
}edge;
bool operator <(Edge a, Edge b)
{
return a.dist > b.dist;
}
priority_queue<Edge> q;
int judge[N][N] = {0};
int pre[N*N/2] = {0};
void init()
{
// memset(judge, 0, sizeof(judge));
for(int i=0; i<N*N/2; i++){
pre[i] = i;
}
}
int Find(int a)
{
return pre[a] == a ? a : pre[a] = Find(pre[a]);
}
void Union(int a, int b)
{
a = Find(a), b = Find(b);
if(a == b){
return;
}
else{
pre[a] = b;
return;
}
}
void Kruskal()
{
int sum = 0;
while(!q.empty()){
edge = q.top();
q.pop();
if(Find(edge.u) != Find(edge.v)){
sum += edge.dist;
Union(edge.u, edge.v);
}
}
cout << sum << endl;
}
int main()
{
int n;
while(cin >> n && n) {
while (!q.empty()) {
q.pop();
}
init();
for (int i = 1; i < n; i++) {//除却最后一个节点
char c;
int t;
cin >> c >> t;
// getchar();
for (int j = 1; j <= t; j++) {
char tc;
int tt;
cin >> tc >> tt;
int u = c-'A', v = tc-'A', l = tt;
q.push(Edge(u, v, l));
}
}
Kruskal();
}
return 0;
}