算法小总结:
朴素版Prim
算法思路:
初始化每个节点到集合的距离为INF
for(0 ~ n - 1)
{
找到集合外离集合最近的点
用该点更新其它点到集合的距离
把点加到集合里面去
}
模拟过程:
858. Prim算法求最小生成树
输入样例:
4 5
1 2 1
1 3 2
1 4 3
2 3 2
3 4 4
代码展示:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 510, INF = 0x3f3f3f3f;
int n, m;
int g[N][N];//存储边权
int d[N];//存储到集合的最短距离
bool st[N];//判断每个节点是不是在集合之中
int prim()
{
memset(d, 0x3f, sizeof d);
int res = 0;
for (int i = 0; i < n; i ++ )
{
int t = -1;
for (int j = 1; j <= n; j ++ )
{
if (!st[j] && (t == -1 || d[t] > d[j]))
{
t = j;
}
}
if (i && d[t] == INF) return INF;//如果不是第一个节点,并且该点到集合的距离为无穷,
//明说明该图不连通
if (i) res += d[t];
//更新其它点到集合的距离
for (int j = 1; j <= n; j ++ )
{
d[j] = min(d[j], g[t][j]);
}
st[t] = true;
}
return res;
}
int main()
{
cin >> n >> m;
memset(g, 0x3f, sizeof g);
for (int i = 0; i < m; i ++ )
{
int a, b, w;
cin >> a >> b >> w;
g[a][b] = g[b][a] = min(g[a][b], w);
}
int t = prim();
if (t == INF) puts("impossible");
else printf("%d\n",t);
}
——————————————————————————————————————————
Kruscal算法
算法思路:
1.将所有的边按权重从小到大排序
2.for(1~m)//枚举每条边
{
if(a 、b不连通)
{
将这条边加入集合中
}
}
模拟过程:
859. Kruskal算法求最小生成树
输入样例:
4 5
1 2 1
1 3 2
1 4 3
2 3 2
3 4 4
代码展示:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 200010, INF = 0x3f3f3f3f;
int n, m;
int p[N];
struct Edge
{
int a, b, w;
bool operator < (const Edge &W)const//重载小于号
{
return w < W.w;
}
}edges[N];
int find(int x)//找到祖宗
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
int kruskal()
{
int cnt = 0, ans = 0;
for (int i = 0; i < m; i ++ )//枚举每条边
{
int a = edges[i].a, b = edges[i].b, w = edges[i].w;
a = find(a);
b = find(b);
if (a != b)
{
p[a] = b;//加到集合之中
ans += w;
cnt ++;
}
}
if (cnt < n - 1) return INF;
return ans;
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i ++ ) p[i] = i;
for (int i = 0; i < m; i ++ )
{
int a, b ,w;
cin >> a >> b >> w;
edges[i] = {a, b, w};
}
sort(edges, edges + m);
int t = kruskal();
if (t == INF) puts("impossible");
else printf("%d\n",t);
}
———————————结束啦,结束啦,堆优化版的Prim太麻烦了,没写——————————