#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define MAX 500
using namespace std;
struct Line{
int start; int end; int lenth;
}line[MAX];
int n, linenumber, minlenth;
int father[MAX], map[MAX][MAX], mark[MAX];
int cmp(Line a, Line b)
{
return a.lenth < b.lenth ? 1 : 0;
}
void initial()
{
int i,j;
linenumber = 0;
for(i = 0; i < n; i++)father[i] = i;
for(i = 0; i < n; i++){
for(j = i + 1; j < n; j++){
if(map[i][j] != 0){
line[linenumber].start = i;
line[linenumber].end = j;
line[linenumber++].lenth = map[i][j];
}
}
}
sort(line, line + linenumber, cmp);
}
int find(int k)//用并查集判断是否产生回路
{
return k == father[k] ? k : father[k] = find(father[k]);
}
void kruscal()//排序后用kruscal算法
{
int i, j;
int a, b;
minlenth = 0;
for(i = 0, j = 0; i < linenumber; i++)
{
a = find(line[i].start); b = find(line[i].end);
if(a != b)//没有产生回路,此路可用
{
father[a] = b;
minlenth += line[i].lenth;
mark[j++] = i;
}
}
}
void input()
{
int i, j;
printf("请输入邻接矩阵:(不相连的节点间的距离视为0,节点到自身的距离也视为0)\n");
for(i = 0; i < n; i++){
for(j = 0; j < n; j++){
scanf("%d", &map[i][j]);
}
}
}
void output()
{
int i;
printf("最小生成树的编集为:\n");
for(i = 0; i < n - 1; i++){
printf("起点:%c ", line[mark[i]].start + 'a');
printf("终点:%c ", line[mark[i]].end + 'a');
printf("长度:%d ", line[mark[i]].lenth);
printf("\n");
}
printf("最小生成树的总长度为:%d\n", minlenth);
}
int main()
{
while(cout << "请输入顶点个数:(输入0结束程序)" << endl && cin >> n && n)
{
input();
initial();
kruscal();
output();
}
if(n == 0)
printf("程序结束!\n");
return 0;
}