Prime
Ptime和Dijkstra有点像,工作原理是每次取距离集合最近的点,将点放入集合中,并更新该点到其他点的距离(dist),这样dist就表示任意节点到集合的最短距离。
题目链接 --Prime算法求最小生成树
#include<iostream>
#include<cstring>
using namespace std;
const int N = 505;
int n, m, G[N][N], dist[N], sum;//G存两点的距离,dist存到生成树的最短距离
bool vis[N];
bool Prime()
{
dist[1] = 0;
for (int i = 0; i < n; i++)
{
int minp = -1;
for (int j = 1; j <= n; j++)
if (!vis[j] && (minp == -1 || dist[j] < dist[minp])) minp = j;
vis[minp] = true;
if (dist[minp] == 0x3f3f3f3f) return false;
sum += dist[minp];
for (int j = 1; j <= n; j++)
if(!vis[j]) dist[j] = min(dist[j], G[minp][j]);
}
return true;
}
int main()
{
memset(G, 0x3f, sizeof G);
memset(dist, 0x3f, sizeof dist);
int u, v, w;
cin >> n >> m;
while (m--)
{
cin >> u >> v >> w;
if (u == v) G[u][v] = 0;//防止自环
else G[u][v] = G[v][u] = min(G[u][v], w);
}
if (Prime()) cout << sum;
else cout << "impossible";
return 0;
}
Kruskal算法
题目链接–Kruskal算法求最小生成树
实现原理:
先按照权重由小到大排序,对于每一条边判断加入树后是否会生成环,如果不生成则加入,更新边两头节点的祖先,否则不加入。
n个节点形成最小生成树边需要n-1,最后判断边数是否满足最小生成树。
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5 + 5;
int n, m, father[N], sum = 0, cnt = 0;
struct edges{
int u, v, w;
}Edges[2*N];
bool cmp(struct edges a, struct edges b)
{
return a.w < b.w;
}
int find(int x)
{
if (x != father[x]) father[x] = find(father[x]);
else return x;
}
int main()
{
int u, v, w;
cin >> n >> m;
//Inti
for (int i = 1; i <= n; i++)
father[i] = i;
for (int i = 0; i < m; i++){
cin >> u >> v >> w;
Edges[i] = {
u,v,w };
}
sort(Edges, Edges + m, cmp);
for (int i = 0; i < m; i++)
{
int a = Edges[i].u, b = Edges[i].v;
a = find(a), b = find(b);//这块注意:将所有点的祖先节点归于同一个点
if (a!=b) {
sum += Edges[i].w;
father[b] = a;//是找到的祖宗节点互相赋予
cnt++;
}
if (cnt == n - 1) cout <<sum;
else cout<<"impossible";
return 0;
}