kruskal算法

裸题传送门

先存后排序

#include <iostream>
#include <stdio.h>
#include <vector>
#include <algorithm>
#define  MAXN 100100
using namespace std;
struct Edge
{
	int point1;
	int point2;
	int weight;
};
bool cmp(Edge &x, Edge &y)
{
	return x.weight < y.weight;
}
int pre[MAXN];
vector <Edge> vec;
int find(int x)
{//并查集
	int root = x;

	while (pre[root] != root)
		root = pre[root];//找根
	int t = x;
	while (pre[t] != root)
	{//路径压缩
		int temp = pre[t];
		pre[t] = root;
		t = temp;
	}

	return root;
}
int main(void)
{
	int n, m;
	int min_sum = 0;

	scanf("%d%d", &n, &m);//n是点数,m是边数
	if (m)
	{
		for (int i = 0; i < n; i++)
			pre[i] = i;//初始化并查集
		for (int i = 0; i < m; i++)
		{//输入每条边的两个顶点及其权重
			Edge temp;

			scanf("%d%d%d", &temp.point1, &temp.point2, &temp.weight);
			vec.push_back(temp);
		}
		sort(vec.begin(), vec.end(), cmp);//按权重对边进行排序
		pre[vec[0].point1] = pre[vec[0].point2];//第一条边绝对在,所以我先把他们连起来
		min_sum += vec[0].weight;//加上权重
		int coun = 1;//此时有了一条已经链接好的边
		for (int i = 1; i < m; i++)
		{//最多只有m条边
			int fx = find(vec[i].point1);
			int fy = find(vec[i].point2);

			if (fx != fy)
			{//如果这条边的两个顶点所在集合不相同就合并
				coun++;//成功合并后就多了一条边
				min_sum += vec[i].weight;
				pre[fx] = fy;//合并
				if (coun == n - 1)
					break;//krusal有n-1条边
			}
		}
		printf("%d\n", min_sum);
	}
	else
		printf("0\n");
	//system("pause");

	return 0;
}

直接存入一个堆(优先队列)中

#include <iostream>
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <queue>
#define  MAXN 100100
using namespace std;
struct Edge
{
	int point1;
	int point2;
	int weight;
};
bool cmp(Edge &x, Edge &y)
{
	return x.weight < y.weight;
}
bool operator < (const Edge& a, const Edge& b) 
{
	return a.weight > b.weight;
}
int pre[MAXN];
priority_queue <Edge> pque;
int find(int x)
{//并查集
	int root = x;

	while (pre[root] != root)
		root = pre[root];//找根
	int t = x;
	while (pre[t] != root)
	{//路径压缩
		int temp = pre[t];
		pre[t] = root;
		t = temp;
	}

	return root;
}
int main(void)
{
	int n, m;
	int min_sum = 0;

	scanf("%d%d", &n, &m);//n是点数,m是边数
	if (m)
	{
		for (int i = 0; i < n; i++)
			pre[i] = i;//初始化并查集
		for (int i = 0; i < m; i++)
		{//输入每条边的两个顶点及其权重
			Edge temp;

			scanf("%d%d%d", &temp.point1, &temp.point2, &temp.weight);
			pque.push(temp);
		}
		pre[pque.top().point1] = pre[pque.top().point2];//第一条边绝对在,所以我先把他们连起来
		min_sum += pque.top().weight;//加上权重
		pque.pop();
		int coun = 1;//此时有了一条已经链接好的边
		while (!pque.empty())
		{//最多只有m条边
			int fx = find(pque.top().point1);
			int fy = find(pque.top().point2);

			if (fx != fy)
			{//如果这条边的两个顶点所在集合不相同就合并
				coun++;//成功合并后就多了一条边
				min_sum += pque.top().weight;
				pre[fx] = fy;//合并
				if (coun == n - 1)
					break;//krusal有n-1条边
			}
			pque.pop();
		}
		printf("%d\n", min_sum);
	}
	else
		printf("0\n");
	//system("pause");

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值