Codeforces Round #529 (Div. 3) F(kul最小生成树)

https://codeforces.com/problemset/problem/1095/F
在这里插入图片描述

题意

给你n个互不相通的点,每个点有权值ai,题目要求将n个点连接生成最小生成树,连接两点的代价是这两个点的权值之和,但是,题目又给你m个特惠,每一个特惠都指定两个点一个特价:x,y,w,他们相连接不一定要以权值为代价,可以使用特价w代替,求代价最小值。

思路

  1. 使用kul建立最小生成树
  2. 选出权值最小的点,e[++t]记录它与其他所有点,以及这两点连接的代价
  3. e[++t]记录特惠。
  4. 针对数组e的w进行从小到大的快排
  5. fa[i] = i ( i 从1到n)
  6. for(i , 1 , t) (遍历e数组)
  7. 并查集的内容,记录连接次数
  8. 连接次数到n-1就退出
  9. 输出答案
  10. 用prim的话,你得做加边操作(可能用到前向星(数组模拟邻接表)),然后循环n-1次,每次去遍历当前节点的连接边,太过麻烦,而且这题是稀疏图,适合使用kul算法。

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e5 + 10, inf = 0x3f3f3f3f3f3f3f3f;
struct node{
	int u,v,w;
	bool operator < (const node& A) const{
		return w < A.w;
	}
}e[N];
int fa[N],a[N],MinIndex,Min = inf,t,times,ans;
int find(int x){
	if (fa[x] != x) return fa[x] = find(fa[x]);
	return x;
}
signed main()
{
	ios::sync_with_stdio(false);
	int n,m;
	cin >> n >> m;
	for (int i = 1; i <= n ;i++){
		cin >> a[i];
		if (Min > a[i])
			Min = a[i],
			MinIndex = i;
	}
	for (int i = 1; i <= n; i++){
		if (i != MinIndex)
			e[++t].u = MinIndex,
			e[t].v = i,
			e[t].w = Min + a[i];
	}
	for (int i = 1; i <= m; i++){
		t++;
		cin >> e[t].u >> e[t].v >> e[t].w;
	}
	sort(e+1,e+1+t);
	for (int i = 1; i <= n; i++) fa[i] = i;
	for (int i = 1; i <= t; i++){
		int u = e[i].u, v = e[i].v;
		if (find(u) != find(v)){
			fa[find(u)] = find(v);
			ans += e[i].w;
			times++;
			if (times == n-1) break;
		}
	}
	cout << ans << "\n";
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值