题记(14)--还是畅通工程

目录

一、题目内容

二、输入描述

三、输出描述

四、输入输出示例

五、完整C语言代码


一、题目内容

某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。

二、输入描述

测试输入包含若干测试用例。每个测试用例的第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算法求解

五、完整C语言代码

AC代码~

#include 
#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 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;
}

你可能感兴趣的:(算法)