Kruscal算法C++实现

原理:使用贪心算法。先将所有边按照权值从小到大排序,每个点初始都是一个树(一个节点的树)。从前到后遍历边集,对于当前边x-y来说,如果x、y已经在我们的最小生成树里,那么跳过该边。

如果x、y至少有一个不在我们的最小生成树里,将该边加入最小生成树,并且将包含x的树和包含y的树合并为一棵树。(使用并差集的合并操作完成)

注:代码未验证正确性!

//Kruscal算法  2020年3月29日 21:41:19

//----------------------------------

vector<int> father; //并差集

void merge(int x,int y){
    int x_father=get_father(x),y_father=get_father(y);
    father[x]=y_father;
}

int get_father(int x){
    if(father[x]!=x){
        return father[x]=get_father(father[x]);
    }
    return x;
}
//-----------------------------------
struct edge     //有权边
{
    int point1;
    int point2;
    int weigh;
    edge(int x,int y,int z):point1(x),point2(y),weigh(z){}
};

//-----------------------------------

//求带权无向图的MST边权和
int Kruscal(){
    int points;//points:点数
    cout<<"输入点个数:"<<endl;
    cin>>points;
    father.resize(points);
    for(int i=0;i<points;++i){
        father[i]=i;
    }
    vector<edge> edges;    //edges:有权边的集合
    int r,s,t;
    while(cin>>r>>s>>t){
        edges.emplace_back(r,s,t);
    }
    sort(edges.begin(),edges.end(),[](const edge& a,const edge& b){return a.weigh<b.weigh;});   //按照权从小到大排序
    int res;    //MST的权和
    int edge_cnt=0;     //已经选入的边数
    for(const auto& edge:edges){
        int p1=edge.point1,p2=edge.point2;
        if(father[p1]==father[p2]){//p1、p2已经加入MST
            continue;
        }
        res+=edge.weigh;//该边加入MST
        ++edge_cnt;
        merge(p1,p2);//合并两个点
        if(edge_cnt>=points-1){//边数为点数-1时,完成了MST的构建
            break;
        }
    }
    return res;
}

猜你喜欢

转载自www.cnblogs.com/FdWzy/p/12595136.html