算法训练 安慰奶牛

Kruskal算法与加权并查集

最小生成树——kruscal算法,使用加权union-find并查集(路径压缩版)数据结构

#include<iostream>
#include<algorithm>
#include<cstdio>
#define  NNUM 10005
#define  PNUM 100005
using namespace std;

int node[NNUM]={0};
int connect[NNUM]={0},sz[NNUM]={0};
int N,P;


struct edge{
	int x,y,d;
}e[PNUM];

int init(){
	scanf("%d%d",&N,&P);
	
	for(int i=0;i<N;i++){
		cin>>node[i];
	}
	
	for(int i=0;i<P;i++){
		scanf("%d%d%d",&e[i].x, &e[i].y,&e[i].d);
		e[i].d=e[i].d*2+( node[e[i].x-1] + node[e[i].y-1]);
	}
	
	
	for(int i=0;i<N;i++){
		connect[i]=i;
	}
}

int cmp(edge e1,edge e2){
	return e1.d<e2.d;
}

int find(int x){
	return connect[x]==x ? x : connect[x]=find(connect[x]);
}
int kruscal(){
	int ans=0;
	sort(e,e+P,cmp);
	for(int i = 0; i < P; i++){
		int xx=find(e[i].x);
		int yy=find(e[i].y);
		if(xx==yy) continue;
		//xx!=yy 则加入树里,ans增加该点权重 
		if(sz[xx]<sz[yy]){
			connect[xx]=yy;
			sz[yy]+=sz[xx];
		}
		else{
			connect[yy]=xx;
			sz[xx]+=sz[yy];
		}
		ans+=e[i].d;
	}
	return ans;
}

int main(){
	
	init();
	int min = 1<<30;
	for(int i = 0; i < N; i++){
		if(node[i] < min) min = node[i];
	}
	//别忘加起点 min 
	printf("%d\n", min+kruscal());
	
	return 0;
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值