目录
某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。
测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。 ??? 当N为0时,输入结束,该用例不被处理。
?对每个测试用例,在1行里输出最小的公路总长度
输入:
3 1 2 1 1 3 2 2 3 4 4 1 2 1 1 3 4 1 4 1 2 3 3 2 4 2 3 4 5 0输出:
3 5
该题本质是求最小生成树,采用Kruskal算法求解
AC代码~
#include <stdio.h>
#define nn 2000
int height[nn];
int father[nn];
typedef struct Number{ // 起始点;终点;边权值
int from;
int to;
int c;
}Num;
Num N[10000];
void init(int n){ // 初始化
for(int i=1;i<=n;i++){
height[i] = 1;
father[i] = i;
}
}
int Find(int x){
if(x!=father[x]){
father[x] = Find(father[x]);
}
return father[x];
}
void Union(int x,int y){
int fx = Find(x);
int fy = Find(y);
if(height[fx] < height[fy]){
father[fx] = fy;
}
else if(height[fx] > height[fy]){
father[fy] = fx;
}
else{
father[fy] = fx;
height[fx]++;
}
}
void SortEdge(Num N[],int n){ // 将图的所有边升序排序
for(int i=n-1;i>0;i--){
for(int j=0;j<i;j++){
if(N[j].c > N[j+1].c){
Num tmp = N[j];
N[j] = N[j+1];
N[j+1] = tmp;
}
}
}
}
int main(){ // Kruskal算法
int n;
while(scanf("%d",&n)!=EOF){
if(n == 0)
break;
for(int i=0;i<(n*(n-1)/2);i++){
scanf("%d%d%d",&(N[i].from),&(N[i].to),&(N[i].c));
}
init(n);
SortEdge(N,n*(n-1)/2);
int T = n; // 连通分量数 减为1时算法结束
int i=0; // N[]即边数组下标
int min_w = 0; // 最小生成树(MST)的权值
while(T>1){ // 开始用Kruskal算法求MST
int x = N[i].from;
int y = N[i].to;
int c = N[i].c;
if(Find(x)!=Find(y)){
Union(x,y);
min_w+=c;
T--;
}
i++;
}
printf("%d\n",min_w);
}
return 0;
}