Kruskal (克鲁斯卡尔)算法(加边法)

时间复杂度O(mlog(m)),用并查集维护
模板代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=2e5+10;;
struct node {
    int x,y,z;
}edge[maxn];


bool cmp(node a,node b) {
    return a.z < b.z;
}

	
int fa[maxn];
int n,m;
int u,v,w; 
long long sum;

int Find(int x) {
    return x == fa[x] ? x : fa[x] = Find(fa[x]);
}

void solve() {
	// Kruskal 算法求最小生成树 
    cin>>n>>m;
	
    for(int i = 1; i <= m; i ++) {
        cin>>edge[i].x>>edge[i].y>>edge[i].z;
    }
    for(int i = 0; i <= n; i ++) {
        fa[i] = i;
    }
    sort(edge + 1,edge + 1 + m,cmp);
    // 每次加入一条最短的边
    for(int i = 1; i <= m; i ++) {
        int x = Find(edge[i].x);
        int y = Find(edge[i].y);
        if(x == y) continue;
        fa[y] = x;
        sum += edge[i].z;
    }
    int ans = 0;
    for(int i = 1; i <= n; i ++) {
        if(i == fa[i]) ans ++;
    }
    if(ans > 1) puts("impossible");
    else printf("%lld\n",sum);


}

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t = 1;
	cin >> t;
    // cout<<"YES";
	while (t--) {
        // init();
		solve();
	}
	return 0;
}

prim(普里姆)算法(加点法)

此处是暴力prim,复杂度达到O(n^2+m)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=505;;
int a[maxn][maxn];
	
int vis[maxn],dist[maxn];

int n,m;

int u,v,w;

long long sum = 0;

int prim(int pos) {
    dist[pos] = 0;
    // 一共有 n 个点,就需要 遍历 n 次,每次寻找一个权值最小的点,记录其下标
    for(int i = 1; i <= n; i ++) {
        int cur = -1;
        for(int j = 1; j <= n; j ++) {
            if(!vis[j] && (cur == -1 || dist[j] < dist[cur])) {
                cur = j;
            }
        }
        // 这里需要提前终止
        if(dist[cur] >= inf) return inf;
        sum += dist[cur];
        vis[cur] = 1;
        for(int k = 1; k <= n; k ++) {
            // 只更新还没有找到的最小权值
            if(!vis[k]) dist[k] = min(dist[k],a[cur][k]);
        }
    }
    return sum;
}

void solve() {
	// prim 算法求最小生成树 
	
    cin>>n>>m;
    memset(a,0x3f,sizeof(a));
    memset(dist,0x3f,sizeof(dist));
    for(int i = 1; i <= m; i ++) {
        cin>>u>>v>>w;
        a[u][v] = min(a[u][v],w);
        a[v][u] = min(a[v][u],w);
    }
    int value = prim(1);
    if(value >= inf) puts("impossible");
    else printf("%lld\n",sum);

}

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t = 1;
	cin >> t;
    // cout<<"YES";
	while (t--) {
        // init();
		solve();
	}
	return 0;
}