[USACO3.1]最短网络 Agri-Net(并查集,最小生成树,排序)

本文介绍了一种优化的并查集实现,通过路径压缩和秩优化提高查找和合并效率。同时,结合插入排序,对边进行预处理,用于克鲁斯卡尔算法求解最小生成树。代码示例展示了如何在输入阶段即完成排序,简化了算法流程,提高了程序性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述
巧妙的优化,观察代码两个循环是否可以联合到一个循环处理,还有本题的排序其实可以在输入的时候就直接处理了

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n;
int mp[10000][10000];
int parent[1005],rank[1005];
struct node{
	int x,y,z;
}edge[10000];
//并查集路径优化 
int find(int x){
	if(x==parent[x])return x;
	return parent[x]=find(parent[x]);
}
//并查集秩优化 
void unio(int x,int y){
	int x_root=find(x);
	int y_root=find(y);
	if(x_root==y_root)return;
	if(x_root>y_root){
		parent[y_root]=x_root;
	}else{
		parent[x_root]=y_root;
		if(x_root==y_root){
			rank[y_root]++;
		}
	}
}
//插入排序 
void charu_sort(int x){
	node pp=edge[x];
	int k=x-1;
	while(pp.z<edge[k].z){
		edge[k+1]=edge[k];
		k--;
	}
	edge[k+1]=pp;
}
int main(){
	scanf("%d",&n);
	int k=0;
	for(int i=1;i<=n;i++){
		parent[i]=i;//初始化优化合并 
		for(int j=1;j<=n;j++){
			cin>>mp[i][j];
			if(j<i){
				if(mp[i][j]!=0){
				edge[k].x=i;
				edge[k].y=j;
				edge[k++].z=mp[i][j];
				}
				if(k>=2){
				charu_sort(k-1);//边输入边排序 
				}
			} 
		}
	}
	//克鲁斯卡尔算法 
	long long count=0,sum=0;
	for(int i=0;i<k;i++){
		if(find(edge[i].x)!=find(edge[i].y)){
			unio(edge[i].x,edge[i].y);
			sum+=edge[i].z;
			count++;
		}
		if(count==n-1){
			break;
		}
	}
	printf("%lld",sum);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值