最小生成树


最小生成树:对于带权图,权值和最小的生成树
最小瓶颈生成树:对于带权图,最大权值最小的生成树
最小生成树一定是最小瓶颈生成树

1:prim:

bool vis[MAXN];
int minc[MAXN];
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > q;
int prim() {
int ans = 0;
q.push(make_pair(0, 1));
while (!q.empty()) {
int c = q.top().first, now = ed[q.top().second].to;
if (!vis[now]) {
vis[now] = true;
ans += c;
insert(ed[i].from, ed[i].to, ed[i].cost);
insert(ed[i].to, ed[i].from, ed[i].cost);
for (int i = he[now]; i; i = ne[i]) {
Edge &e = ed[i];
if (minc[e.to] > e.cost && !vis[e.to]) {
minc[e.to] = e.cost;
q.push(make_pair(e.cost, i));
}
}
}
}
return ans;
}


随意选取一个点作为已访问集合的第一个点,并将所有相连的边加入堆中
-
从堆中找到最小的连接集合内和集合外点的边,将边加入最小生成树中
-
将集合外点标记为已访问,并将相连边加入堆

重复以上过程直到所有点都在访问集合中

2:kruskal

struct UnionSet {
int f[MAXN];
UnionSet(int n) {
for (int i = 1; i <= n; i++) {
f[i] = i;
}
}
UnionSet(){}

void uni(int x, int y) {
f[find(x)] = find(y);
}

bool query(int x, int y) {
return find(x) == find(y);
}

int find(int x) {
return f[x] == x ? x : (f[x] = find(f[x]));
}

} us;

void kruskal() {
sort(edges, edges+m);
us = UnionSet(n);
for (int i = 0; i < m && etop < n * 2 - 1; i++) {
Edge &e = edges[i];
if (!us.query(e.from, e.to)) {
insert(e.from, e.to, e.dist);
insert(e.to, e.from, e.dist);
us.uni(e.from, e.to);
}
}
}


将边按照权值排序

依次枚举每一条边,若连接的两点不连通则加入最小生成树中

使用并查集维护连通性

原文地址:https://www.cnblogs.com/zyfltyyz/p/11719158.html