Loading

一本通最小生成树学习笔记

这里统一采用复杂度最优的Kruskal+最优性剪枝方法,Prim流消失

板子

/*Kruskal算法思路:先把边从小到大排序,然后从小到大选边,选边后将这两个点在并查集中merge一下,然后如果选边之前这两个点已经联通了(find相同)我们就跳过此次选边(因为选择这个边是没有意义的)*/
#include <bits/stdc++.h>
using namespace std;
//Kruskal
//记得输出不连通的情况(orz)
int f[101010];
struct node{
	int x,y,z;
}a[1010101];
int n,m,ans = 0,cnt,tot;
int find(int x){
	if(f[x] != x)  return f[x] = find(f[x]);
	return x;
}
bool cmp(node xx,node yy){
	return xx.z < yy.z;
}
int main(){
	cin>>n>>m;
	for(int i = 1;i <= m;i++){
		++cnt;
		cin>>a[cnt].x>>a[cnt].y>>a[cnt].z;
	}
	sort(a+1,a+cnt+1,cmp);
	for(int i = 1;i <= n;i++){
		f[i] = i;
	}
	for(int i = 1;i <= cnt;i++){
		if(find(a[i].x) != find(a[i].y)){
			ans += a[i].z;
			tot++;
			f[find(a[i].x)] = f[find(a[i].y)];
		}
		if(tot == n-1){
			cout<<ans<<endl; 
			return 0;
		}
	}
	puts("impossible");
}

【一本通提高篇最小生成树】北极通信网络

//需要手动生成一下图
#include <bits/stdc++.h>
using namespace std;
//Kruskal
int f[1010100];
struct node {
	int x, y;
} a[1010101];
struct edge {
	int x, y;
	double z;
} e[1010101];
int n, m,  cnt, tot;
double ans;
int find(int x) {
	if (f[x] != x)  return f[x] = find(f[x]);
	return x;
}
bool cmp(edge xx, edge yy) {
	return xx.z < yy.z;
}
double calc(int i, int j) {
	return sqrt((a[i].x - a[j].x) * (a[i].x - a[j].x) + (a[i].y - a[j].y) *
	            (a[i].y - a[j].y));
}
int main() {
	int t;
	cin >> t;
	while (t--) {
		scanf("%d%d",&n,&m);
		tot = 0,ans = 0,cnt = 0;
		for (int i = 1; i <= m; i++) {
			scanf("%d%d", &a[i].x, &a[i].y);
		}
		for (int i = 1; i <= m; i++) {
			for (int j = i+1; j <= m; j++) {
				e[++cnt] = {i, j, calc(i, j)};
			}
		}
		sort(e + 1, e + cnt + 1, cmp);
		for (int i = 1; i <= m; i++) {
			f[i] = i;
		}
		for (int i = 1; i <= cnt; i++) {
			if (find(e[i].x) != find(e[i].y)) {
				ans += e[i].z;
				tot++;
				f[find(e[i].x)] = f[find(e[i].y)];
			}
			if (tot == m - n) {
				printf("%.2lf\n",e[i].z);
				goto endd;
			}
		}
endd:
		;
	}
}

【一本通提高篇最小生成树】新的开始

/*超级源点思路:每个点i都和编号为0的点连一个边权为v[i]的边*/
#include <bits/stdc++.h>
using namespace std;

struct node {
	int fr, to, l;
} e[101000];
int tot, ans;
int n;
int f[101000];
int cnt;
int v[100000];
bool cmp(node xx, node yy) {
	return xx.l < yy.l;
}
int find(int x) {
	return f[x] == x ? x : f[x] = find(f[x]);
}
void merge(int x, int y) {
	f[find(x)] = f[find(y)];
}
int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> v[i];
		e[++cnt] = {i, 0, v[i]};
	}
	for (int i = 1; i <= n; i++) f[i] = i;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			int cost;
			cin >> cost;
			e[++cnt] = {i, j, cost};
		}
	}
	sort(e + 1, e + 1 + cnt, cmp);
	for (int i = 1; i <= cnt; i++) {
		if (find(e[i].fr) != find(e[i].to)) {
			merge(e[i].fr, e[i].to);
			tot++;
			ans += e[i].l;
		}
		if (tot == n) break;//n-1个点,然后还需要再建一个发电站
	}
	cout << ans << endl;
}

posted @ 2025-05-13 20:01  FrankWkd  阅读(7)  评论(0)    收藏  举报