写在前面:首先吐槽一下学校的OJ,题目上说是输入字母结果后台测试样例却出现数字= =!害得我改来改去提交了7次都是错的。(呸
回到正题
题目描述
已知有权无向图G,利用克鲁斯卡尔算法求出该图的最小生成树。
输入
第一行输入两个正整数n和m(空格间隔), 分别表示图G的顶点总数和边的总数。
第二行连续输入n个字母,分别表示n个顶点的信息。
第三行连续输入m条边的信息,每条边的输入格式为(v1,v2,w),表示一条关联顶点v1和v2的边,其权值为w。
输出
按边上权值由小到大的顺序依次输出各个边。
输出边的时,若该边被选中,则在该边信息之后输出1,否则输出0。
例如:
(v1,v2,w,1) 表示与顶点v1和v2相关联的边,权值为w,被选中。
(v1,v2,w,0) 表示与顶点v1和v2相关联的边,权值为w,未被选中。
解题思路
看到这道题,就是想到用邻接矩阵来存储,然后将题目信息依次输入。克鲁斯卡尔算法是将权重排序,然后从最小的开始取,如果不构成环就将边加入,如果构成环就舍弃,也就是题目中说的1和0。最主要的问题就是我们要不停的检查是否构成环,其实这里应该可以用DFS来判断连通分量(不会所以放弃了)。所以就采用了前几天在博客上看到的并查集。
并查集由一个整数型的数组和两个函数构成。数组pre[]记录了每个点的前导点是什么,函数find是查找,join是合并(这道题没有用到)。
int Find(int *parent, int f) {
while (parent[f] > 0) {
f = parent[f];
}
return f;
}
我们很容易通过并查集来判断这些点是否都在一个集合里,如果在的话就将边舍弃,如果不在的话就放入。
刚学并查集,理解还不是很深刻,日后再补啦!
下面贴上本题代码
#include