Kruskal与Prim最小生成树

Kruskal算法

算法思想

前置算法-并查集

将所有边依据边权进行排序,从边权最小的边开始枚举,利用并查集判断这条边的两个点是否已经连通,如果已经连通,就跳过这条边,当已经连了n-1条边,说明已经求出了最小生成树。

Code-C++

#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 2e5 + 10, inf = 0x3f3f3f3f;

struct Edge
{
    int a, b, c;
}edges[maxn];
int n, m;
int f[maxn];

int find(int x)
{
    if (f[x] != x) f[x] = find(f[x]);
    return f[x];
}

bool cmp(Edge a, Edge b)
{
    return a.c < b.c;
}

int kurskal()
{
    for (int i = 1; i <= n; i++) f[i] = i;
    int res = 0, cnt = 0;
    sort(edges ,edges + m , cmp);
    for (int i = 0; i < m; i++)
    {
        int a = find(edges[i].a), b = find(edges[i].b);
        if (a != b)
        {
            res += edges[i].c;
            f[a] = b;
            cnt++;
        }
        if (cnt == n - 1) return res;
    }
    return inf;

}

int main()
{
    cin >> n >> m;
    for (int i = 0; i < m; i++)
    {
        cin >> edges[i].a >> edges[i].b >> edges[i].c;
    }
    int t = kurskal();
    if (t == inf) cout << "orz" << endl;
    else cout << t << endl;
    return 0;
}

Prim算法

算法思想

与dijkstra求最短路相似,从起点开始连接距离最短的点,不同的是每次最短的距离是所有不连通的点和已经连通的图之间的最短距离,每次更新一个点,所以这些距离也就可以只更新每一次更新的点相连的点的距离。

Code-C++

#include <iostream>
#include <cstring>

using namespace std;

const int maxn = 5050, inf = 0x3f3f3f3f;

int n, m;
int g[maxn][maxn];
int dist[maxn];
bool vis[maxn];

int prim()
{
    memset(dist, 0x3f, sizeof dist);
    int res = 0;
    for (int i = 0; i < n; i++)
    {
        int t = -1;
        for (int j = 1; j <= n; j++)
        {
            if (!vis[j] && (t == -1 || dist[t] > dist[j]))
            {
                t = j;
            }
        }
        if (i && dist[t] == inf) return inf;
        if (i) res += dist[t];
        vis[t] = true;
        for (int j = 1; j <= n; j++)
        {
            dist[j] = min(dist[j], g[t][j]);
        }
    }
    return res;
}

int main()
{
    memset(g, 0x3f, sizeof g);
    cin >> n >> m;
    while (m--)
    {
        int a, b, c;
        cin >> a >> b >> c;
        g[a][b] = g[b][a] = min(g[a][b], c);
    }
    auto t = prim();
    if (t == inf) cout << "orz" << endl;
    else cout << t << endl;
    return 0;
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容