最小生成树

Prim

dijkstra算法基本思想相同,唯一不同的是dis表示的不同,在dijkstra中,dis[i]表示i点到起点的最短距离,在Prim中,dis[i]表示i点到已经维护好的树的最短距离。

复杂度O(n2+m)O(n^2+m)

朴素算法:

struct Node {
    int y, v;
    Node(int  _y, int _v) { y = _y, v = _v; }
};
vector<Node>edge[1010];
int n, m, dis[1010];
bool b[1010];
int Prim() {
    memset(b, false, sizeof(b));
    memset(dis, 127, sizeof(dis));
    dis[1] = 0;//任意设一个起点开始找最短路
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        int x = -1;
        for (int j = 1; j <= n; j++) {
            if (!b[j] && dis[j] < 1 << 30) {
                if (x == -1 || dis[j] < dis[x])
                    x = j;
            }
        }
        b[x] = true;
        ans += dis[x];
        for (auto j : edge[x]) {
            dis[j.y] = min(dis[j.y], j.v);
        }
    }
    return ans;
}
void solve() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; i++) {
        int x, y, z;
        scanf("%d%d%d", &x, &y, &z);
        edge[x].push_back({ y,z });
        edge[y].push_back({ x,z });
    }
    int ans=Prim();
    printf("%d\n", ans);
}

Prim优化:

通过优先队列(priority_queue)来优化,可以将时间复杂度优化至O((n+m)logn)O((n+m)logn)

注意当图中的边特别满的时候,该算法的可能比朴素算法更慢

Kruskal

Prim算法每次加点,而Kruskal算法则是通过每次加边来实现

时间复杂度为O(mlogn)O(mlogn)

Last updated