最小生成树板板

prim朴朴素素 

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,minn,k,ans;
const int INF=0x7fffffff/2;
int f[1000000],mn[1000000];
int a[5001][5001];
int x,y,w;
int main() {
	int i,j;
	scanf("%d%d",&n,&m);
	memset(a,0x7f,sizeof(a));
	for(i=1; i<=m; i++) {
		scanf("%d%d%d",&x,&y,&w);
		a[y][x]=a[x][y]=min(a[y][x],w);
	}
	memset(mn,0x7f,sizeof(mn));
	mn[1]=0;
	for(i=1; i<=n; i++) {
		minn=INF;
		for(j=1; j<=n; j++)
			if(f[j]==0&&mn[j]<minn) {
				minn=mn[j];
				k=j;
			}
		f[k]=1;
		ans+=minn;
		for(j=1; j<=n; j++)
			if(f[j]==0&&mn[j]>a[k][j]) mn[j]=a[k][j];
	}
	cout<<ans<<endl;
	return 0;
}

prim结构体

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define INF 0x7f7ff; 
using namespace std;
int n,m,head[5010],x,y,z,cnt,ans;
int mn[5010],f[5010];
struct deliver{
	int to;
	int nexty;
	int w;
}edge[400010];
void add(int u,int v,int c) {
	cnt++;
	edge[cnt].nexty=head[u];
	edge[cnt].to=v;
	edge[cnt].w=c;
	head[u]=cnt;
}
int main() {
	int i,j,k;
	cin>>n>>m;
	for(i=1;i<=m;i++) {
		scanf("%d%d%d",&x,&y,&z);
		add(x,y,z);
		add(y,x,z);
	}
	memset(mn,0x7f,sizeof(mn));
	mn[1]=0;
	for(i=1;i<=n;i++) {
		int minn=INF;
		for(j=1;j<=n;j++) {
			if(f[j]==0&&mn[j]<minn) {
				k=j;
				minn=mn[j];
			}
		}
		f[k]=1;
		ans+=mn[k];
		for(j=head[k];j;j=edge[j].nexty) {
			int r=edge[j].to;
			if(f[r]==0&&mn[r]>edge[j].w) mn[r]=edge[j].w;
		}
	}
	cout<<ans<<endl;
	return 0;
}

krus

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int n,m,ans,cnt;
int f[200009];
struct deliver {
	int z;
	int x;
	int y;
}b[200009];
int find(int k) {
	if(f[k]==k) return k;
	f[k]=find(f[k]);
	return f[k];
}
int cmp(deliver p,deliver q) {
	return p.z<q.z;
}
void krs() {
	int i;
	for(i=1;i<=m;i++) 
		if(find(b[i].x)!=find(b[i].y)) {
			ans+=b[i].z;
		    f[find(b[i].x)]=find(b[i].y);
		    cnt++;
		    if(cnt==n-1) break;
	    }
}
int main() {
	int i,j,k;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++) 
	   f[i]=i;
	for(i=1;i<=m;i++) {
		scanf("%d%d%d",&b[i].x,&b[i].y,&b[i].z);
		//f[find(b[i].x)]=find(b[i].y);多余 
	}
	sort(b,b+m+1,cmp);
	krs();
	cout<<ans;
	return 0;
} 

 

### 关于最小生成树算法的解题模板 #### Kruskal 算法示例代码 Kruskal 算法的核心思想是通过不断选取权重最小的边来构建最小生成树,同时确保不会形成环路。以下是基于并查集实现的 Kruskal 算法模板: ```python class UnionFind: def __init__(self, n): self.parent = list(range(n)) def find(self, x): if self.parent[x] != x: self.parent[x] = self.find(self.parent[x]) return self.parent[x] def union(self, x, y): rootX = self.find(x) rootY = self.find(y) if rootX != rootY: self.parent[rootY] = rootX def kruskal(edges, n): edges.sort(key=lambda edge: edge[2]) # 按照权重从小到大排序 uf = UnionFind(n) mst_weight = 0 mst_edges = [] for u, v, w in edges: if uf.find(u) != uf.find(v): # 如果两个节点不在同一个连通分量中 uf.union(u, v) mst_weight += w mst_edges.append((u, v, w)) if len(mst_edges) != n - 1: # 判断是否构成一棵生成树 return None return mst_edges, mst_weight ``` 上述代码实现了 Kruska 算法的基础逻辑[^2]。 --- #### Prim 算法示例代码 Prim 算法则采用贪心策略逐步扩展已有的生成树集合。以下是基于邻接矩阵实现的 Prim 算法模板: ```python import heapq def prim(graph, start=0): n = len(graph) visited = [False] * n min_heap = [(0, start)] # (weight, node) mst_weight = 0 mst_edges = [] while min_heap: weight, u = heapq.heappop(min_heap) if visited[u]: continue visited[u] = True mst_weight += weight for v, w in enumerate(graph[u]): if not visited[v] and w > 0: heapq.heappush(min_heap, (w, v)) mst_edges.append((u, v, w)) if sum(visited) != n: # 判断是否所有节点都被访问过 return None return mst_edges, mst_weight ``` 此代码展示了如何利用堆优化的方式加速 Prim 算法的执行效率[^1]。 --- #### 示例应用 假设有一个无向加权图表示如下(邻接表形式),可以通过调用以上函数解决最小生成树问题: 输入样例: ```plaintext edges = [ (0, 1, 7), (0, 3, 5), (1, 2, 8), (1, 3, 9), (2, 3, 7), (2, 4, 5), (3, 4, 15), (3, 5, 6), (4, 5, 8), (4, 6, 9), (5, 6, 11) ] n = 7 # 节点数 m = len(edges) # 边数 ``` 运行 `kruskal(edges, n)` 或者将 `graph` 构建为邻接矩阵后运行 `prim(graph)` 即可得到对应的最小生成树及其总权重[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值