#include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #define DEBUG #ifdef DEBUG #define debug(...) printf( __VA_ARGS__) #else #define debug(...) #endif #define N 27 #define MAX_INT 20000000 using namespace std; struct eg{ char x; char y; int w; }; struct eg edge[75]; char parent[N]; /* MF Set, 树根的parent为负数,其绝对值表示这棵树的高度 */ int n, m; /* 找i的根节点 */ int find(int i) { for(; parent[i] >= 0; i = parent[i]) ; return i; } void merge(int x,int y, int px, int py) { if (px == py) return; debug("%d的树根为%d,树高=%d,%d的树根为%d, 树高=%d\n", x, px, -parent[px], y, py, -parent[py]); if (parent[px] < parent[py]) { /* x所在的树比y所在的树要高 */ parent[py] = px; debug("合并后树根为%d, 高度=%d\n", px, -parent[px]); } else if (parent[px] > parent[py]) { /* x所在的树比y所在的树要矮 */ parent[px] = py; debug("合并后树根为%d, 高度=%d\n", py, -parent[py]); } else { parent[py] = px; parent[px]--; /* 树的高度加1 */ debug("合并后树根为%d, 高度=%d\n", px, -parent[px]); } } static int compare(const void *p1, const void *p2) { return ((struct eg *)p1)->w - ((struct eg *)p2)->w; } int kruskal() { int i, total_cost; int px, py; total_cost = 0; qsort(edge, m, sizeof(eg), compare); /* 按边的长度从小到大排序 */ memset(parent, -1, sizeof(parent)); for (i = 0; i < m; i++) { debug("%c-%c : %d\n", edge[i].x+'A', edge[i].y + 'A', edge[i].w); } for (i = 0; i < m; i++) { px = find(edge[i].x); py = find(edge[i].y); if (px != py) { /* 这条边的两个顶点不在同一个集合中 */ merge(edge[i].x, edge[i].y, px, py); debug("边%c-%c加入集合, 长度为%d\n", edge[i].x+'A', edge[i].y+'A', edge[i].w); total_cost += edge[i].w; } } return total_cost; } int main() { int i, j, w; char ch; char adj; while (cin >> n && n) { m = 0; for (i = 1; i < n; i++) { cin >> ch >> j; while (j--) { cin >> adj >> w; edge[m].x = ch-'A'; edge[m].y = adj-'A'; edge[m].w = w; m++; } } debug("总共有%d条边\n", m); printf("%d\n", kruskal()); } return 0; }