图的最小生成树,Kruskal算法

lixiaotao 2020-06-06

最小生成树 kruskal 算法,适用于边稀疏的图,

先按照边进行排序。

取出小的边

选出小的,判断边的两个顶点是否是同一连通分量。如果是则继续取出下一个边。否则输出两个顶点,并合并两个连通分量。

需要注意的是一开始需要一个辅助数组来记录连通分量,初始化所有顶点自己是一个连通分量。当合并两个连通分量时,需要遍历这个数组,将其中一个设置成另一个连通分量的值。

struct Edge{
    int head;
    int tail;
    int lowcost;
};

bool compare(const Edge& e1, const Edge& e2) {
    return e1.lowcost < e2.lowcost;
}
void MiniSpanTree_Kruskal(vector<vector<int> > G) {
    int m = G.size();
    vector<Edge> edge;
    vector<int> Vex(m);//连通分量
    //将图转成边存储
    for(int i = 0;i<m;i++){
        Vex[i] = i;//初始连通分量为其自身
        for(int j = 0;j<m;j++){
            if(j == i || G[i][j] == -1) continue;
            Edge e;
            e.head = i;
            e.tail = j;
            e.lowcost = G[i][j];
            edge.push_back(e);
        }
    }
    sort(edge.begin(),edge.end(),compare);
    for(int i = 0;i<edge.size();i++){
        int v0 = edge[i].head, v1 = edge[i].tail;
        if(Vex[v0] == Vex[v1]) continue; // 如果v0和v1是同一个连通分量,就找下一个
        cout<<v0<<v1;
        int temp = Vex[v1];
        for(int j = 0;j<m;j++){
            if(Vex[j] == temp) {
                Vex[j] = Vex[v0]; //更新v1的连通分量,并入到v0
            }
        }
    }
}

相关推荐