Prim

const int maxn = 5e2 + 7;

int n;              //点的个数
int dis[maxn];      //标记当前到某点的最短距离
bool vis[maxn];     //标记某点是否已经在树里
int e[maxn][maxn];  //邻接矩阵存图

//因为prim算法时间复杂度O(n*n),广泛用于稠密图,所以用邻接矩阵是一个合适的选择

int Prim() {
    int ans = 0;
    for (int i = 0; i <= n; ++i) dis[i] = 2e9, vis[i] = 0;  //初始化
    dis[1] = 0;  // prim算法任选起点,于是可以选择1为起点
    for (int i = 1; i <= n; ++i) {
        int u = 0;  //注意dis[0]已经初始化为无穷大了,不用管了
        for (int j = 1; j <= n; ++j)
            if (!vis[j] && dis[j] < dis[u]) u = j;
        vis[u] = 1;
        ans += dis[u];  //更新答案
        for (int j = 1; j <= n; ++j)
            if (!vis[j] && dis[j] > e[u][j])  //拿u点来更新新拓展的边
                dis[j] = e[u][j];
    }
    return ans;  //生成树总长度
}

Kruskal

#include <algorithm>
const int maxn = 500 + 7;
const int maxm = 500 * 500 + 7;
int n;         //点的数量
int m;         //边的数量
struct edge {  //边
    int u;     //起点
    int v;     //终点
    int w;     //权重
} edges[maxm];
// Kruskal算法的前置知识是并查集,来判断已选边是否成环
//设点数量为n,边数量为m,Kruskal算法的时间复杂度为O(n)+O(m*logm)
int bin[maxn];  //每个节点对应的根节点的信息
void unit() {   //初始化
    for (int i = 0; i <= m; i++) bin[i] = i;
}
void merge(int x, int y) {  //并
    int fx = Find(x);
    int fy = Find(y);
    if (fx != fy) bin[fx] = fy;
}
int Find(int x) {  //查
    int px = x;
    while (px != bin[px]) px = bin[px];
    return px;
}
bool cmp(edge a, edge b) {  //将边按照权重从小到大排序
    return a.w < b.w;
}
int Kruskal() {
    int sumweight = 0;  //生成树的权值
    int num = 0;        //已选用的边的数目
    int u, v;           //选用边的两个顶点
    unit();             //初始化 parent[]数组
    std::sort(edges, edges + m);
    for (int i = 0; i < m; i++) {
        u = edges[i].u;
        v = edges[i].v;
        if (Find(u) != Find(v)) {
            //如果满足不成环,就加入生成树
            sumweight += edges[i].w;
            num++;
            merge(u, v);
        }
        if (num == n - 1) break;  //边的数量达到n-1条时,生成树构建完成
    }
    return sumweight;
}