Kruskal算法

Kruskal算法

  • 问题描述
  • 算法简析
  • 代码

问题描述

有一张 n n n 个顶点、 m m m 条边的无向图,且是连通图,求最小生成树。

算法简析

K r u s k a l Kruskal Kruskal 是一种求最小生成树的算法。
设该图为 G = ( V , E ) G = (V, E) G=(V,E)。最小生成树即所求为 G T = ( V T , E T ) G_T = (V_T, E_T) GT=(VT,ET),因为图是连通的,所以最小生成树会覆盖所有的顶点,即 V = = V T V == V_T V==VT G T G_T GT真子图 G A = ( V A , E A ) G_A = (V_A, E_A) GA=(VA,EA) V A = = V V_A == V VA==V,构成森林(注意,这里与 P r i m Prim Prim 并不一样。 G A G_A GA 初始状态就覆盖所有顶点,每个顶点各自为一棵树)。
因为 G A G_A GA 已经覆盖了所有顶点,所以 G − G A G - G_A GGA 只剩下 G G G 中所有的边 E E E。为了让 G A G_A GA 从森林变成一棵树,我们需要从 E E E 中挑选边加入 G A G_A GA。例如,我们选择 e ( u , v ) e(u, v) e(u,v) 加入 G A G_A GA,本来独立的 u u u v v v 被连接起来,相当于 u u u v v v 各自所在的两棵树要合并成一棵树。
为了得到最小生成树,我们采用贪心策略,每次都从 E E E 中挑选最短的边 e ( u , v ) e(u, v) e(u,v),如果 u u u v v v 还不在一棵树上,就将该边加入 G A G_A GA,同时合并两棵树。
为了能够高效地合并树,我们采用并查集。

代码

typedef struct
{
    int from, to, worth;
} edge;

vector<edge> E;

// Kruskal
bool cmp(const edge &a, const edge &b)
{
    return a.worth < b.worth;
}

int kruskal(void)
{
    int ret = 0;
    init();
    sort(E.begin(), E.end(), cmp);          // 升序
    for (int i = 0; i < E.size(); i++)
    {
        edge e = E[i];
        if (!same(e.from, e.to))            // 判断是否在一棵树中
        {
            ret += e.worth;
            unite(e.from, e.to);            // 合并树
        }
    }
    return ret;
}

你可能感兴趣的:(algorithms,算法)