Problem Description
當前農村公路建設正如火如荼的展開,某鄉鎮政府決定實現村村通公路,工程師現有各個村落之間的原始道路統計數據表,表中列出了各村之間可以建設公路的若干條道路的成本,你的任務是根據給出的數據表,求使得每個村都有公路連通所需要的最低成本。
Input
連續多組數據輸入,每組數據包括村落數目N(N <= 1000)和可供選擇的道路數目M(M <= 3000),隨後M行對應M條道路,每行給出3個正整數,分別是該條道路直接連通的兩個村莊的編號和修建該道路的預算成本,村莊從1~N編號。
Output
輸出使每個村莊都有公路連通所需要的最低成本,如果輸入數據不能使所有村莊暢通,則輸出-1,表示有些村莊之間沒有路連通。
Sample Input
5 8
1 2 12
1 3 9
1 4 11
1 5 3
2 3 6
2 4 9
3 4 4
4 5 6
Sample Output
19
Hint
Source
xam
思路:
prim算法
注:
設頂點集A爲最小生成樹的點集;頂點集B爲待處理點集
lowcost[i]用來保存,頂點集A到i頂點的最小代價。
lowcost數組初始化爲INF(無窮大)
隨着結點的不斷併入,lowcost數組的值不斷更新
爲0代表該結點已併入A頂點集
爲INF代表該結點與A頂點集無直接邊相連
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define INF 0x3f3f3f3f // 必須定義一個接近無窮大的數
int vexnum, edgenum; // 頂點數和邊數
int map[1005][1005]; // 鄰接矩陣
int lowcost[1005];
int result = 0; // 累加器
int prim() // 普里姆算法
{
int i, j, k, min;
lowcost[1] = 0; // 頂點集A中併入1號頂點,即從1號頂點開始
for (i = 2; i <= vexnum; i++) // 更新lowcost數組
{
lowcost[i] = map[i][1];
}
for (i = 2; i <= vexnum; i++) // 通過n-1次循環,併入n-1個點
{
min = INF;
j = 1;
k = 0;
while(j <= vexnum) // 找到頂點集A的最小代價邊
{
if (lowcost[j] != 0&& lowcost[j] < min) // 保證不成環且最小
{
min = lowcost[j];
k = j;
}
j++;
}
if (min == INF) // 進行判斷,若頂點集A不再有邊,退出循環
{
break;
}
result += min; // 累加權值
lowcost[k] = 0; // 將K號頂點併入頂點集A
for (j = 1; j <= vexnum; j++) // 通過新併入的K號頂點,更新lowcost數組
{
if (lowcost[j] != 0&&lowcost[j] > map[j][k])
{
lowcost[j] = map[j][k];
}
}
}
for (i = 1; i <= vexnum; i++) // 判斷是否所有邊都併入頂點集A
{
if (lowcost[i] != 0) // 若有頂點爲併入頂點集A,則圖不連通
{
return -1;
}
}
return result;
}
int main()
{
int i,u,v,c;
while(~scanf("%d %d",&vexnum,&edgenum))
{
result=0;
memset(map,INF,sizeof(map));
memset(lowcost,INF,sizeof(lowcost));
for(i=1;i<=edgenum;i++)
{
scanf("%d %d %d",&u,&v,&c);
map[u][v]=c;
map[v][u]=c;
}
int value = prim();
printf("%d\n", value);
}
return 0;
}