/*
* 1251.cpp
* 纯粹MST。。 Prim实现
*
* Created on: 2011-9-2
* Author:
*
* 开始用scanf, WA, 后改成cin, AC了~ 不知怎么回事 总之对C的输入输出理解的还不够好~
*/
#include <cstdio>
#include <iostream>
usingnamespace std;
constint maxN =27+5;
constint inf =100000000;
int n, w[maxN][maxN], d[maxN], ans;
intbase='A'-1;
int inline min(int lhs, int rhs){
return lhs < rhs ? lhs : rhs;
}
//同1258的模板~
int mstPrim(){
for(int i=1; i<=n; i++)
d[i] = inf;
int cur =1, minEdge, minNode;
ans =0;
for(int i=1; i<n; i++){
d[cur] =-1;
minEdge = inf;
for(int j=1; j<=n; j++){
if(cur != j && d[j] !=-1){
d[j] = min(d[j], w[cur][j]);
if(d[j] < minEdge){
minEdge = d[j]; minNode = j;
}
}
}
cur = minNode;
ans += minEdge;
}
return ans;
}
int main(){
while(cin >> n){
if(n==0) return0;
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++)
w[i][j] = inf;
}
char curNode, nextNode;
int edgeNum, edgeW, iCurNode, iNextNode;
for(int i=1; i<n; i++){
//scanf("%s%d", &curNode, &edgeNum);
cin >> curNode >> edgeNum;
iCurNode = curNode -base;
for(int j=1; j<=edgeNum; j++){
// scanf("%s%d", &nextNode, &edgeW);
cin >> nextNode >> edgeW;
iNextNode = nextNode -base;
w[iCurNode][iNextNode] = w[iNextNode][iCurNode] = edgeW;
}
}
mstPrim();
printf("%d\n", ans);
}
return0;
}
/*
* DA-term-Main-Mirror3.cpp.cpp
*
scanf 用%s即可
* Created on: 2011-12-8
*
*/
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 27 + 5;
const int maxE = 75 + 5;
int n, edgeNum;
struct SEdge{
int w;
char u, v;
};
SEdge edge[maxE];
struct SData{
char name;
char p;
int num;
};
SData node[maxn];
bool inline cmp(const SEdge a, const SEdge b){
return a.w < b.w;
}
char find(char cur){
if(node[cur-'A'].p == cur)
return cur;
node[cur-'A'].p = find(node[cur-'A'].p);
return node[cur-'A'].p;
}
void merge(char u, char v){
int up = find(u);
int vp = find(v);
if(up == vp) return;
if(node[up-'A'].num < node[vp-'A'].num){
node[up-'A'].p = vp;
node[vp-'A'].num += node[up-'A'].num;
}
else{
node[vp-'A'].p = up;
node[up-'A'].num += node[vp-'A'].num;
}
}
int kruskal(){
sort(edge, edge+edgeNum, cmp);
int ans = 0;
for(int i=0; i<edgeNum; i++){
if(find(edge[i].u) == find(edge[i].v))
continue;
merge(edge[i].u, edge[i].v);
ans += edge[i].w;
}
return ans;
}
int main(){
char tmpName[2], nextName[2];
int tmpW, tmpNum;
while(scanf("%d", &n), n){
for(int i=0; i<n; i++){
node[i].p = 'A' + i;
node[i].num = 1;
}
edgeNum = 0;
for(int i=0; i<n-1; i++){
scanf("%s%d", tmpName, &tmpNum);
for(int j=0; j<tmpNum; j++){
scanf("%s%d", nextName, &tmpW);
edge[edgeNum].w = tmpW;
edge[edgeNum].u = tmpName[0];
edge[edgeNum++].v = nextName[0];
}
}
int ans = kruskal();
printf("%d\n", ans);
}
return 0;
}