最小生成树

\(Prim\)

思路

类似于\(dijkstra\)​,每次从当前已选过的点中连边选出最优的一个添加,并把该点加入集合。时间复杂度为\(O(n^2)\)。可以进行堆优化,但优化后时间复杂度仍与\(kruskal\)相当且代码复杂,适用于稠密图。

\(Code\)

int Prim(){
    memset(dist, 0x3f3f3f3f, sizeof(dist));
    int res = 0;
    for(int i = 1; i <= n; i++){
        int w = -1;
        for(int j = 1; j <= n; j++)
            if(!vis[j] && (w == -1 || dist[j] < dist[w]))
                w = j;
        if(i != 1 && dist[w] == INF) return INF;
        if(i != 1)   res += dist[w];
        for(int j = 1; j <= n; j++)
            dist[j] = min(dist[j], g[w][j]);
        vis[w] = true;
    }
    return res;
}

\(Kruskal\)

思路

基于对边的排序,对边从小到大排序后,每次判断两点是否已经有连通,每次判断最短的边添加,用并查集查询是否能添加。时间复杂度为\(O(e\log e)\)​​​。

\(Code\)

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

int kruskal(){
	sort(e+1, e+m+1, cmp);
	for(int i = 1; i <= n; i++)	fa[i] = i;
	int res = 0, cnt = 0;
	for(int i = 1; i <= m; i++){
		int a = e[i].a, b = e[i].b, w = e[i].w;
		a = find(a), b = find(b);
		if(a != b){
			fa[a] = b;
			res += w;
			cnt++;
		}
	}
	if(cnt < n - 1)	return INF;
	return res;
}
posted @ 2024-10-09 18:31  Zzzzzzzm  阅读(11)  评论(0)    收藏  举报