最小生成树--Kruskal

Kruskal 代码模板

基本思路:
        新手初学,使用优先队列,免去排序;并查集判环,过程中进行了路径压缩,以提高效率; 然后贪心建立最小生成树, min为最小权值;
        算法演示: http://sjjg.js.zwu.edu.cn/SFXX/sf1/kruskal.html

        另外,同为最小生成树的Prime算法和Kruskal算法的适用问题:
               因为Prime算法只于顶点有关,所以它更适用于稠密图
               而Kruskal算法依据于边的权值,所以边越少它速度越快,更适合稀疏图

#include <stdio.h>
#include <queue>
#define N 100

using namespace std;

struct Node{
	int start;
	int end;
	int price;
	friend bool operator < (const Node& a, const Node& b){
		return a.price > b.price;
	}
};

priority_queue<Node>q;
int v, l;					// v为顶点数, l为边数
int father[N];

int get_father(int cur)
{
	return cur == father[cur] ? cur : father[cur] = get_father(father[cur]);		// 路径压缩
}

int join(int start, int end)
{	
	int root1 = get_father(start);
	int root2 = get_father(end);

	if(root1 == root2)
		return 0;
	father[root1] = root2;
	return 1;
}

int kruskal()
{
	int ans = 0;
	Node cur;

	while(!q.empty()){			// 此处可记录边数,以优化
		cur = q.top();
		q.pop();

		if(join(cur.start, cur.end)){
			printf("%d -> %d\n", cur.start, cur.end);		// 输出路径
			ans += cur.price;
		}
	}

	return ans;
}

int main()
{
	int i;
	Node a;
	scanf("%d%d", &v, &l);
	for(i = 0; i < v; i ++){
		father[i] = i;
	}

	for(i = 0; i < l; i ++){
		scanf("%d%d%d", &a.start, &a.end, &a.price);
		q.push(a);
	}

	printf("\nRoad: \n");

	int min = kruskal();			// 最小生成树

	printf("LowLoad: %d\n", min);

	printf("\nFather:  \n");		// 输出father数组
	for(i = 0; i < v; i ++)
		printf("%d ", father[i]);
	printf("\n");
	
	return 0;
}


你可能感兴趣的:(最小生成树,图论,kruskal,并查集)