Kruskal算法

Kruskal算法是求最小生成树的一种算法,运用了贪心的思想,十分常用。算法流程大体如下:将m条边按边权从小到大排序,枚举每条边,如果该边的起点和终点已经在最小生成树中,则跳过,否则就将这条边加入到最小生成树中。具体实现方面会借助于并查集,来判断两个点是否在最小生成树中(已连通)。

 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 using namespace std;
 5 
 6 struct Edge {
 7     int u, v, w;
 8     bool operator < (const Edge& rhs) const {
 9         return w < rhs.w;
10     } //规定边的优先级用于排序
11 } edge[maxm];
12 
13 int n, m, fa[maxn];
14 
15 int dj_find(int i) {
16     if (i == fa[i]) return i;
17     else return fa[i] = dj_find(fa[i]);
18 }
19 
20 inline void dj_merge(int a, int b) {
21     a = dj_find(a), b = dj_find(b);
22     if (a != b) fa[a] = b;
23 } //定义并查集的查询合并操作
24 
25 inline int Kruskal() {
26     int cnt = 0, sum = 0;
27     for (int i = 1; i <= n; ++i) fa[i] = i;
28     sort(edge + 1, edge + m + 1); //按边权排序
29     for (int i = 1; i <= m; ++i) {
30         int u = edge[i].u, v = edge[i].v;
31         if (dj_find(u) != dj_find(v)) {
32             dj_merge(u, v);
33             sum += edge[i].w;
34             ++cnt;
35         } //若边的起点和终点之前未连通,则连通
36         if (cnt == n - 1) return sum;
37     } //最小生成树有n-1条边
38     return -1;
39 }
Kruskal算法

 

呃呃,附上一道裸题,USACO习题最短网络,在洛谷上的链接为:https://www.luogu.org/problemnew/show/P1546

 

posted @ 2017-08-22 20:24  Mr^Kevin  阅读(382)  评论(0编辑  收藏  举报