keep moving

boruvka 算法朴素实现

Posted on By condy

wiki 上面讲得还是很详细的。

过程就是:

寻找连通分量之间的最短边;

连接;

#include <iostream>
#include <vector>
#include <algorithm>
#include <istream>
#include <cmath>

using namespace std;

#define VERTEX_NUMBER 12

struct edge_t {
    int a, b;
    int weight;

    edge_t() {}
    edge_t(int _a, int _b, int _w):a(_a), b(_b), weight(_w) {}
};

istream& operator>>(istream& in, edge_t& elem)
{
    char ch1, ch2;
    int weight;

    in >> ch1 >> ch2 >> elem.weight;
    elem.a = ch1 - 'a';
    elem.b = ch2 - 'a';

    return in;
}

ostream& operator<<(ostream& out, edge_t& elem)
{
    char ch1 = elem.a + 'a', ch2 = elem.b + 'a';
    out << ch1 << "-->" << ch2 << ' ' << elem.weight << endl;
    return out;
}

int f[VERTEX_NUMBER];

void init()
{
    for (int i = 0; i < VERTEX_NUMBER; ++i)
        f[i] = i;
}

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

vector<edge_t> boruvka(const vector<edge_t>& GE)
{
    int N, i;
    edge_t closest[VERTEX_NUMBER];
    vector<edge_t> ret;
    vector<edge_t> E(GE);

    const edge_t inf(-1, -1, INFINITY);
    init();

    // find all possible edges
    for (int e = E.size(); e > 0; e = N) {
        for (int j = 0; j < VERTEX_NUMBER; ++j)
            closest[j] = inf;

        // select the active edges between 2 components
        for (i = N = 0; i < e; ++i) {
            int a = find(E[i].a), b = find(E[i].b);

            // if they are in the same forest
            if (a == b)
                continue;

            if (closest[a].weight > E[i].weight)
                closest[a] = E[i];
            if (closest[b].weight > E[i].weight)
                closest[b] = E[i];
            E[N++] = E[i];
        }

        // for every component
        for (int j = 0; j < VERTEX_NUMBER; ++j) {
            if (closest[j].weight == INFINITY || find(closest[j].a) == find(closest[j].b))
                continue;
            int a = find(closest[j].a), b = find(closest[j].b);
            f[a] = b;
            ret.push_back(closest[j]);
        }
    }
    return ret;
}

int main()
{
    edge_t e;
    vector<edge_t> E;
    vector<edge_t> mst;

    while (cin >> e)
        E.push_back(e);

    mst = boruvka(E);
    for (int i = 0; i < mst.size(); ++i)
        cout << mst[i];

    return 0;
}

针对上面的程序,附一测试数据(其实就是wiki上的那幅图):

a b 13

a c 6

b c 7

b d 1

c d 14

c e 8

c h 20

d 3 9

d f 3

e f 2

e j 18

g h 15

g i 5

g j 19

g k 10

h j 17

i k 11

j k 16

j l 4

k l 12