最小生成树

Kruskal’s Algorithm
  • 每次添加一条边到T中
  • 按cost的非降序选边,且不构成环

可以用min heap来存边,以简化找权值最小的边的过程

  • Initialize: O(e)
  • the next edge to be chosen or deleted: O(loge)
  • worst case of this process: O(eloge+e)
    If the graph is represented by adj matrix or adj list, its representation should be converted to edges array which is expressed as (u,v,weight)

判断新加的点是否会导致形成一个环
本质上是看u,v是否在同一个component

  • 并查集
    把每个component存储一个set
    s1 = find(u);
    s2 = find(v);
    if(s1 != s2) union(s1,s2);
#include <vector>
#include <algorithm>
using namespace std;

#define MAXV 1000
#define INF 1e9

struct edge {
	int u, v;
	int cost;
} E[MAXV];

bool cmp(edge a, edge b) {
	return a.cost < b.cost;
}

int father[MAXV];

int findFather(int x) {
	if (x == father[x])
		return x;
	int z = findFather(father[x]);
	father[x] = z;
	return z;
}

int kruskal(int n, int m) {
	//n: num of v       m:num of e
	int ans = 0, numE = 0;
	for (int i = 0; i < n; i++) {
		father[i] = i;
	}
	sort(E, E + m, cmp);
	for (int i = 0; i < m; i++) {
		int faU = findFather(E[i].u);
		int faV = findFather(E[i], v);
		if (faU != faV) {
			father[faU] = faV;
			ans += E[i].cost;
			numE++;
			if (numE == n - 1)
				break;
		}
	}
	if (numE != n - 1)
		return -1;
	else
		return ans;
}

Prim’s Algorithm

想法

  • Begin with a tree T that contains an arbitrary single vertex.
  • Add a least-cost edge (u,v) to T such that T∪{(u,v)} is kept as a tree. Note that edge (u,v) is such that exactly one of u and v is in T.
  • Repeat this edge-addition step until T contains n-1 edges.

实现

#include <vector>
using namespace std;

#define MAXV 1000
#define INF 1e9

struct Node {
	int v, dis;
};

vector<Node> adj[MAXV];

int n;
int d[MAXV];
bool vis[MAXV] = {false};

int prim() {
	fill(d, d + MAXV, INF);
	d[0] = 0;
	int ans = 0;
	for (int i = 0; i < n ; i++) {
		int u = -1, MIN = INF;
		for (int j = 0; j < n; j++) {
			if (vis[j] == false && d[j] < MIN) {
				u = j;
				MIN = d[j];
			}
		}
		if (u == -1)
			return -1;
		vis[u] = true;
		ans += d[u];
		for (int j = 0; j < adj[u].size(); j++) {
			int v = adj[u][j].v;
			if (vis[v] == false && adj[u][j].dis < d[v]) {
				d[v] = G[u][v];
			}
		}
	}
	return ans;
}

时间复杂度:
普里姆算法的时间复杂度为O(n2),与网中的边数无关,因此适用于求稠密网的最小生成树。

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值