最小生成树——kruskal算法

  1. 将n个顶点看成n个集合
  2. 按权值由小到大的顺序选择边,所选边应满足两个顶点不在同一个顶点集合内,将该边放到生成树的结合边中,同时也将该边的两个定点放到生成树的顶点集中
  3. 重复前两个(注意:所加的边不能构成环,所以在以下代码中用find函数检测将该边加入是否存在环)

适合于稀疏图——顶点多边少

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const int INF=0x3f3f;
//边集数组 
typedef struct Edg
{
    int begin;//该边的起始点 
    int end;//该边的结束点 
    int weight;//该边的权值 
    Edg()
    {
        begin=end=weight=0;
    }
}Edg;
class Cmp
{
    public:
        bool operator() (const Edg &a,const Edg &b)
        {
            return a.weight<=b.weight;    
        }
};
class Graph
{
    private:
        int num;
        int e;
        vector<vector<int> > arr;
        vector<Edg> edg;
        vector<int> tree;
        int find(vector<int> &t,int n);//判断该边的两个定点是否都在最小生成树的集合中,v[t]=k,t是边的起始点,k是边的结束点 
    public:
        Graph();
        ~Graph();
        void kruskal();
};
Graph::Graph()
{
    cout<<" num"<<endl;
    cin>>num;
    cout<<" e"<<endl;
    cin>>e;
    
    arr.resize(num);
    for(int i=0;i<num;++i)
    {
        arr.at(i).resize(num);
        fill(arr.at(i).begin(),arr.at(i).end(),INF);
    }
    
    edg.resize(num);//
    tree.resize(num,-1);//最小生成树的顶点集合,该集合中最多和图中的点一样多 
    
    cout<<" 输入边的两个端点&&权值"<<endl;
    pair<int,int> info;
    for(int i=0;i<e;++i)
    {
        cin>>info.first>>info.second;
        cin>>arr.at(info.first-1).at(info.second-1);
        arr.at(info.second-1).at(info.first-1)=arr.at(info.first-1).at(info.second-1);
    }
}
Graph::~Graph()
{
    //cout<<"~Graph()"<<endl;    
}
int Graph::find(vector<int> &t,int n)
{
    while(t.at(n)>0)
        n=t.at(n);
    return n;
} 
void Graph::kruskal()
{
    //储存边的信息,只存储邻接矩阵的对角线右上部分,无向图 
    for(int i=0;i<num;++i)
        for(int j=i+1;j<num;++j)
        {
            if(arr.at(i).at(j)<INF)
            {
                edg.at(i).begin=i;
                edg.at(i).end=j;
                edg.at(i).weight=arr.at(i).at(j);
            }
        }
    
    //按权值从小到大把边集排序
    sort(edg.begin(),edg.end(),Cmp());
    for(int i=0;i<num;++i)
    {
        int t=find(tree,edg.at(i).begin);
        int t1=find(tree,edg.at(i).end);
        if(t1!=t)
        {
            tree.at(t)=t1;
            cout<<"<"<<edg.at(i).begin<<","<<edg.at(i).end<<"> weight:"<<edg.at(i).weight<<endl;
        }
    }
}
int main()
{
    Graph g;
    g.kruskal();
    return 0;
}
原文地址:https://www.cnblogs.com/tianzeng/p/10458471.html