作为一个伪ACMer,先来首广为人知的打油诗:
模拟只会猜题意,贪心只能过样例,数学上来先打表,规律一般是DP,组合数学碰运气,计算几何瞎暴力,图论一顿套模板,数论只会GCD,递归递推伤不起,搜索茫然TLE,分治做得像枚举,暴力枚举数第一,数据结构干瞪眼,怒刷水题找信心。
写在前面:
目录:
跟Kruskal算法一样Prim算法也是解决最小生成树问题的一种经典算法。最小生成树问题是指在一个无向带权图中,找到一棵树,使得树的所有边的权值之和最小,并且包含图中的所有顶点。
Prim算法是一种基于顶点的贪心算法,适用于稠密图。它从任意一个顶点开始,每次选择一个与当前生成树最近的顶点,并将该顶点和相应的边加入生成树中。重复此过程,直到所有顶点都被包含在生成树中。
最小生成树 的概念
最小生成树(Minimum Spanning Tree,MST)是图论中的一个经典问题,它指的是在一个加权无向图中找到一个边的子集,使得这个子集构成的树包含图中的所有顶点,并且边的权重之和最小。
说人话就是在一个有n个顶点的稠密图中用n-1条边连接n个顶点,然后每条边都带有权值,求满足条件的这n-1条边的总的权值和的最小值。
最小生成树在网络设计、电路设计等领域有着广泛的应用。
下面我们以这个图为例,用Prim算法求它的最小生成树:
最后输出: 最小的权值和 res=38
#include<bits/stdc++.h>
using namespace std;
// typedef long long int;
#define int long long
const int N = 1005;
const int inf = 1e9+10;
int dist[N],res=0; //dist[]储存到集合S的距离,res保存结果。
int g[N][N]; // g[i][j]表示顶点i和顶点j之间的权值为g[i][j]
bool vis[N];//用来标记这个顶点是否已选过
int n,m; // n个顶点 m条边
void prim(){
vis[1]=1; //把点1加入集合S,点1在集合S中,将它到集合的距离初始化为
dist[1]=0; // 从顶点1出发
for(int i=2;i<=n;i++)dist[i]=min(dist[i],g[1][i]); // 用顶点1去更新它周围顶点的距离
for(int i=2;i<=n;i++){
int t=-1;// 初始化下标
int cnt=inf;//初始化距离
for(int j=2;j<=n;j++){
if(!vis[j]&&dist[j]<cnt){
t=j;
cnt=dist[j]; // 存储最小的权值
}
}
if(t==-1){
res=inf; // 说明没找到 构造不了最小生成树 终止
return ;
}
res+=cnt; // 总权值
vis[t]=1; // 标记
for(int j=2;j<=n;j++)dist[j]=min(dist[j],g[j][t]); ////用新加入的点来更新dist[]
}
}
void solve(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
g[i][j]=inf; //先初始化每两个顶点间的距离为无穷大
}
dist[i]=inf;
}
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
g[u][v]=g[v][u]=w; //由于是无向边,我们对g[a][b]和g[b][a]都要赋值
}
prim();
if(res==inf)//如果res的值是正无穷,表示不能该图不能转化成一棵树,输出orz
cout<<"orz";
else
cout<<res;//否则就输出结果res
}
signed main(){
freopen("input.in", "r", stdin);
freopen("out.txt", "w", stdout);
int _=1;
while(_--){
solve();
}
return 0;
}
代码实战
"纸上得来终觉浅,绝知此事要躬行".也许看完了上面的解析,你已经最prim算法有了一个大致的了解,学习算法,大致的了解是远远不够的,代码的实践永远是最重要的,学习完一个算法后一定要去自己亲手试试,每个人都有自己的代码风格,大家大可以在自己的风格之上写出自己prim。
Prim | 简介 | 难度 |
P3366 【模板】最小生成树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) | 模版题 | ★☆☆☆☆ |
P1967 [NOIP2013 提高组] 货车运输 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) | 基本应用 | ★☆☆☆☆ |
P1991 无线通讯网 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) | 基本应用 | ★☆☆☆☆ |
第一题是模板题,后面两题主要是更好得帮助我们理解最小生成树——prim在实际和题目中得应用。
最后感谢未来的大犇你能够看到最后,也希望各位能支持一下本彩笔(1赞十道1500算法题)Orz