最小生成树Prim算法

文章作者:甘航  文章来源:http://www.cnblogs.com/ganhang-acm/转载请注明,谢谢合作。

由于数据结构老师布置的一道题 ,我看prim算法看了半天还是一知半解。

在浏览过n多大神博客后半copy半自动补脑完成了这道渣渣题。、、

题目就是从老师给的两个文件中读取数据求最小生成树。

第一个城市文件

北京 0, 上海 1, 天津 2, 石家庄 3, 太原 4, 呼和浩特 5, 沈阳 6, 长春 7,哈尔滨  8,
济南 9, 南京 10, 合肥 11, 杭州 12, 南昌 13, 福州 14, 台北 15, 郑州 16, 武汉 17,
长沙 18, 广州 19, 海口 20, 南宁 21, 西安 22, 银川 23, 兰州 24, 西宁 25,
乌鲁木齐  26, 成都 27, 贵阳 28, 昆明 29, 拉萨 30,  * -1,
city.txt

第二个各城市之间距离文件

 1 0
 2 1078 0
 3 119 963 0
 4 263 989 262 0
 5 398 1096 426 171 0
 6 401 1381 504 394 341 0
 7 634 1189 605 867 1025 987 0
 8 866 1451 860 1117 1264 1171 281 0
 9 1061 1679 1068 1318 1457 1325 512 232 0
10 367 735 271 266 412 650 790 1065 1287 0
11 905 269 798 769 854 1161 1155 1432 1664 540 0
12 902 399 806 730 790 1114 1227 1507 1738 537 141 0
13 1135 160 1025 1010 1095 1403 1314 1582 1813 775 242 328 0
14 1255 601 1169 1049 1065 1405 1607 1887 2118 899 467 380 447 0
15 1568 606 1465 1403 1452 1783 1785 2053 2282 1201 668 674 472 441 0
16 1729 686 1620 1590 1655 1978 1870 2124 2349 1367 827 866 596 687 252 0
17 626 824 582 376 359 700 1158 1428 1645 374 560 463 787 706 1103 1317 0
18 1052 685 981 823 816 1157 1484 1765 1993 720 456 319 566 270 705 945 459 0
19 1343 881 1277 1104 1074 1411 1782 2063 2291 1019 704 584 733 291 666 916 730 299 0
20 1893 1210 1819 1662 1637 1973 2280 2561 2792 1553 1136 1054 1051 674 697 869 1291 842 563 0
21 2286 1666 2223 2042 1991 2315 2714 2995 3225 1964 1581 1490 1506 1115 1137 1276 1666 1243 946 455 0
22 2050 1599 2001 1794 1720 2029 2535 2815 3041 1757 1459 1344 1441 1004 1171 1366 1424 1054 762 505 373 0
23 909 1218 913 654 516 770 1518 1770 1970 780 949 824 1147 908 1348 1589 437 644 778 1306 1587 1274 0
24 879 1597 947 720 555 535 1504 1703 1860 964 1335 1237 1564 1404 1836 2067 777 1134 1298 1825 2082 1748 521 0
25 1178 1717 1228 977 807 870 1812 2026 2193 1185 1448 1328 1653 1401 1842 2087 906 1144 1229 1698 1889 1533 507 346 0
26 1321 1908 1381 1138 968 981 1950 2151 2306 1359 1640 1520 1845 1589 2030 2276 1094 1334 1408 1858 2021 1657 699 448 192 0
27 2399 3265 2502 2336 2192 1999 2909 2998 3057 2599 3004 2902 3229 3020 3461 3704 2444 2758 2848 3278 3378 3005 2114 1668 1622 1440 0
28 1511 1655 1518 1258 1114 1320 2123 2375 2572 1370 1404 1264 1543 1166 1573 1824 1003 976 908 1235 1339 971 604 885 596 691 2053 0
29 1732 1522 1702 1469 1368 1649 2278 2551 2768 1488 1320 1185 1378 938 1256 1493 1123 867 647 761 816 449 880 1318 1087 1207 2570 523 0
30 2085 1956 2071 1823 1700 1942 2662 2929 3139 1878 1750 1614 1812 1370 1666 1892 1505 1295 1080 1087 959 619 1187 1526 1226 1288 2494 641 434 0
31 2558 2909 2604 2347 2179 2237 3192 3402 3561 2528 2653 2514 2799 2414 2800 3046 2194 2233 2141 2324 2220 1883 1758 1701 1380 1255 1592 1257 1574 1266 0
distance.txt

要求是根据这两个文件数据 求个城市最小生成树;

下面给出具体代码

代码的注释我写得很详细,方便理解,有几点需要说明一下。

1、2个for循环都是从1开始的,因为一般我们默认开始就把第0个节点加入生成树,因此之后不需要再次寻找它。

2、lowcost[i]记录的是以节点i为终点的最小边权值。初始化时因为默认把第0个节点加入生成树,因此lowcost[i] = graph[0][i],即最小边权值就是各节点到0号节点的边权值。

3、mst[i]记录的是lowcost[i]对应的起点,这样有起点,有终点,即可唯一确定一条边了。初始化时mst[i] = 0,即每条边都是从0号节点出发。

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4 #define inf 1<<30
 5 #define node_num 31// 图的节点数
 6 struct node
 7 {
 8     char s[20];//存城市名字
 9     int id;//这个可以不要,可以用c的下标表示
10 } c[node_num];
11 int G[node_num][node_num];//图的矩阵表示
12 int Prim()
13 {
14     int lowcost[node_num];/* lowcost[i]记录以i为终点的边的最小权值,当lowcost[i]=0时表示终点i加入生成树 */
15     int mst[node_num];/* mst[i]记录对应lowcost[i]的起点,当mst[i]=0时表示起点i加入生成树 */
16     int i,j,min,minid,sum=0;
17 
18     for(i=1; i<node_num; i++)/* 默认选择0号节点加入生成树,从1号节点开始初始化 */
19     {
20         lowcost[i]=G[0][i];/* 最短距离初始化为其他节点到0号节点的距离 */
21         mst[i]=0;/* 标记所有节点的起点皆为默认的0号节点 */
22     }
23     mst[0]=0;/* 标记0号节点加入生成树 */
24     for(i=1; i<node_num; i++)/* n个节点至少需要n-1条边构成最小生成树 */
25     {
26         min=inf;
27         minid=0;
28         for(j=1; j<node_num; j++)/* 找满足条件的最小权值边的节点minid */
29         {
30             if(lowcost[j]<min&&lowcost[j]!=0)/* 边权值较小且不在生成树中 */
31             {
32                 min=lowcost[j];
33                 minid=j;
34             }
35         }
36         printf("%s -- %s: %d
",c[mst[minid]].s,c[minid].s,min);/* 输出生成树边的信息:起点,终点,权值 */
37 
38         sum+=min;/* 累加权值 */
39 
40         lowcost[minid]=0;/* 标记节点minid加入生成树 */
41         for(j=1; j<node_num; j++)/* 更新当前节点minid到其他节点的权值 */
42         {
43             if(G[minid][j]<lowcost[j])/* 发现更小的权值 */
44             {
45                 lowcost[j]=G[minid][j];/* 更新权值信息 */
46                 mst[j]=minid;/* 更新最小权值边的起点 */
47             }
48         }
49     }
50     return sum;/* 返回最小权值和 */
51 }
52 int main()
53 {
54     int i,j,w;
55     for(i=0; i<node_num; i++)
56         for(j=0; j<node_num; j++)
57         {
58             G[i][j]=G[j][i]=inf;/* 初始化图,所有节点间距离为无穷大 */
59         }
60         //读取城市信息
61     freopen("city.txt","r",stdin);
62     for(i=0; i<node_num; i++)
63     {
64         scanf("%s",c[i].s);
65         scanf("%d,",&c[i].id);
66     }
67     //读取各城市之间的距离(权值)
68     freopen("distance.txt","r",stdin);
69     for(i=0; i<node_num; i++)
70         for(j=0; j<=i; j++)
71         {
72             scanf("%d",&w);
73             if(w!=0)
74                 G[i][j]=G[j][i]=w;
75         }
76 
77     int sum=Prim();//求最小生成树
78      printf("总长度:%d",sum);//输出最小权值和
79     return 0;
80 }
Prim_v1.1
随便写写。一点学习心得。。。--如果本文章没有注明转载则为原创文章,可以随意复制发表,但请注明出处与作者
原文地址:https://www.cnblogs.com/ganhang-acm/p/4143978.html