题目描述 Description
一个国家有n个城市。若干个城市之间有电话线连接,现在要增加m条电话线(电话线当然是双向的了),使得任意两个城市之间都直接或间接经过其他城市有电话线连接,你的程序应该能够找出最小费用及其一种连接方案。
输入描述 Input Description
输入文件的第一行是n的值(n<=100).
第二行至第n+1行是一个n*n的矩阵,第i行第j列的数如果为0表示城市i与城市j有电话线连接,否则为这两个城市之间的连接费用(范围不超过10000)。
输出描述 Output Description
输出文件的第一行为你连接的电话线总数m,第二行至第m+1行为你连接的每条电话线,格式为i j,(i<j), i j是电话线连接的两个城市。输出请按照Prim算法发现每一条边的顺序输出,起始点为1.
第m+2行是连接这些电话线的总费用。
样例输入 Sample Input
5
0 15 27 6 0
15 0 33 19 11
27 33 0 0 17
6 19 0 0 9
0 11 17 9 0
样例输出 Sample Output
2
1 4
2 5
17
数据范围及提示 Data Size & Hint
n<=100
这个题是非常标准的Prim最小生成树的问题。他的输出顺序可以先用一个二维下标为2的数组存储,最后结束的时候打印出来即可。
直接上代码
/************************************************************************* > File Name: 电话连线.c > Author: zhanghaoran > Mail: 467908670@qq.com > Created Time: 2015年05月25日 星期一 10时03分14秒 ************************************************************************/ #include <stdio.h> #include <string.h> #define INF 100000 int Prim(int a[][100], int n){ int low[100]; int b[100][2]; int used[100]; int closeset[100]; int i, j, k, min; int flag = 0; int icount = 0; int count = 0; int t = 0; for(i = 0; i < n ; i ++){ low[i] = a[0][i]; used[i] = 0; closeset[i] = 0; } used[i] = 0; for(i = 0; i < n - 1; i++){ j = 0; min = INF; for(k = 1; k < n; k ++) if(!used[k] && low[k] < min){ j = k; min = low[k]; if(min == 0){ flag = 1; break; } } used[j] = 1; count += min; if(flag == 0){ icount ++; b[t][0] = j + 1 < closeset[j] + 1 ? j + 1 : closeset[j] + 1; b[t][1] = j + 1 > closeset[j] + 1 ? j + 1 : closeset[j] + 1; //用来存储最后输出的数据 t ++; } flag = 0; //如果中间连通的话那么就不将其存储 for(k = 1; k < n; k ++) if(!used[k] && a[j][k] < low[k]){ low[k] = a[j][k]; closeset[k] = j; } } printf("%d ", icount); for(i = 0; i < icount; i++){ printf("%d %d ", b[i][0], b[i][1]); } return count; } int main(void){ int n; int a[100][100]; int i, j; scanf("%d", &n); for(i = 0; i < n; i ++){ for(j = 0; j < n; j ++){ scanf("%d", &a[i][j]); } } printf("%d ", Prim(a, n)); }