生成树机制实验(1)Kruskal-1
算法描述
Kruskal算法基于贪心思想。首先把所有边按照权值先从小到大排列,接着按照顺序选取每一条边,如果这条边的两个端点不属于同一集合,那么就将它们合并,直到所有的点都属于同一个集合为止。
基于并查集的贪心算法
算法流程:
对于图 G(V,E),算法描述如下:
输入: 图 G
输出: 图 G 的最小生成树
(1) 将图G看做一个森林,每个顶点为一棵独立的树
(2) 将所有的边加入集合S,一开始 S = E
(3) 从 S 中取出一条权值最短的边(u,v), 如果(u,v) 不在同一棵树内,则连接 u,v 合并这两棵树,同时将 (u,v) 加入生成树的边集 E'。
(4) 重复(3) 直到所有点都属于同一棵树,边集 E' 就是一棵最小生成树
算法的时间复杂度为O(|E|log|E|)
畅通工程(杭电1863)
省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。编写程序,计算出全省畅通需要的最低成本。
Input
测试输入包含若干测试用例。每个测试用例的第 1 行给出评估的道路条数 N、村庄数目M(<100);随后的 N 行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从 1 到 M 编号。当 N 为 0 时,全部输入结束,相应的结果不要输出。
Output
对每个测试用例,在 1 行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出"?"。
Sample Input
3 3
1 2 1
1 3 2
2 3 4
1 3
2 3 2
0 100
Sample Output
3
?
- 首先解决一下输入的问题:
while(scanf("%d%d",&n,&m),n+m)
/*首先由于 scanf对于 %d 的输入,遇到空格即表示结束,所以
scanf("%d%d",&n,&m)与 scanf("%d %d",&n,&m)等价
例如输入2 3,第一个scanf("%d%d",&n,&m),由于遇到了2空格,表示第一个输入结束,把字符串'2'转成整型2,下一个'3'' ',把字符串'3'改为整型3*/
(scanf("%d%d",&n,&m),n+m) 是逗号表达式
第一个表达式是 scanf("%d%d",&n,&m),第二个表达式是 n+m
逗号表达式的运算顺序从左到右依表达式次序执行,但是:
逗号表达式的结果等于最后一个表达式的结果
例如:表达式1,表达式2,表达式3,…,表达式n
结果等于表达式 n 的结果
先执行 scanf("%d%d",&n,&m),读入2个整数,n,m,送返2–如果成功读入了这2个数,送返1–如果成功读入了1个数,送返0–如果输入失败。
再执行 n + m ,这里的 n,m用scanf读入的值,逗号表达式结果等于 n+m
所以这道题,当N等于0时标记结束,故可以写成:
while(scanf("%d%d",&n,&m),n){}
- 其次介绍一下C语言封装的qsort()函数
# include <stdlib.h>
void qsort(void *base, size_t n_elements, size_t el_size,int(*compare)(void const*,void const*))
void *base: 指向需要排序的数组
size_t n_elements: 指定数组中元素的数目
size_t el_size: 指定每个元素的长度,以字节为单位
int (*compare)(void const*,void const*):函数指针
举个例子:
# define MAX 10000 + 10
typedef struct{
int a,b,price;
}Node;
Node a[MAXN];
int cmp(const void*a,const void*b){
return ((Node*)a)->price - ((Node*)b)->price;
}
qsort(a,n,sizeof(a[0]),cmp);
/*a: 指向需要排序的结构体数组, n: 结构体数组的元素个数 sizeof(a[0]):结构体成员的大小
cmp: 定义的函数*/
- 回调函数
qsort()属于回调函数,排序时,要执行两个元素比较大小的操作,比大小这个操作必须知道数据类型,如果把这个操作交给用户来做,就可以编写出与数据类型无关的排序函数。
用户调用库函数 qsort,库函数 qsort 调用用户编写的比较函数cmp, 这样的用法称为回调函数。
qsort中提前定义好用户函数的封装格式,参数列表以及函数的功能含义,不允许修改,用户只能编写功能代码,不能改变函数封装和功能含义。
qsort的回调函数原型是:
int (*compare)(void const*,void const*)
//(*compare)是一个函数指针,用函数指针代替具体的函数名,使用前必须赋值,指向一个具体的函数