最小生成树
最小生成树
一般来说,最小生成树的题目大多与图的连通性和最小边权和有关,因此就很容易想到一种十分容易实现的算法:
先按照边权排序,再从最小的边开始枚举,若联通且不产生回路,就加入到生成树中,直到加到\(N-1\)条边为止(即已经成为了树且不形成回路)
那问题来了,代码怎么写,不难想到可以使用并查集,把所有的顶点加入并查集,枚举到就查询是否有相同的祖先即可。
代码如下:
#include<iostream>
using namespace std;
struct edge {
int u;//点
int v;//点
int w;//权值
};
struct edge e[10];//为了方便排序,使用了结构体来存储这些边
int n, m;
int f[7] = { 0 };//并查集用
void quicksort(int left, int right) {
int i, j;
struct edge t;
if (left > right) {
return;
}
i = left, j = right;
while (i != j) {
//先从右边找
while (e[i].w >= e[left].w && i < j) {
j--;
}
//再从左边找
while (e[i].w <= e[left].w && i < j) {
i++;
}
//交换
if (i < j) {
t = e[i];
e[i] = e[j];
e[j] = t;
}
}
//最后把基准数归位,把left和i互换
t = e[left];
e[left] = e[i];
e[i] = t;
quicksort(left, i - 1);//处理左边
quicksort(i + 1, right);//处理右边
return;
}
void init(int n) {
for (int i = 1; i <= n; i++) {
f[i] = i;
}
}
int getf(int v) {
if (f[v] == v) {
return v;
}
else {
//路径压缩
f[v] = getf(f[v]);
return f[v];
}
}
int merge(int v, int u) {
int t1, t2;
t1 = getf(v), t2 = getf(u);
if (t1 != t2) {
f[t2] = t1;
return 1;
}
return 0;
}
int main(){
int i, sum = 0, count = 0;
cin >> n >> m;
//n为顶点数,m为边数
for (int i = 1; i <= m; i++) {
cin >> e[i].u >> e[i].v >> e[i].w;
}
quicksort(1, m);
init(n);
for (int i = 1; i <= m; i++) {
if (merge(e[i].u, e[i].v)) {
count++;
sum += e[i].w;
}
if (count == n - 1) {
break;
}
}
cout << sum;
return 0;
}

浙公网安备 33010602011771号