最小生成树–kruskal

也加克鲁斯卡尔算法。

kruskal算法的思想简单说来就是:每次选择图中最小边权的边,如果边两端的顶点在不同的连通块中,就把这条边加入最小生成树中。

如果是稠密图(边多),用prim算法;如果是稀疏图(边少),用kruskal算法,或者用我自己想的“做减法”。

//对于kruskal算法来说,由于需要判断边的两个端点
//是否在不同的连通块中,因此边的两个端点的编号是一定
//需要的;而算法中有涉及边权,因此边权也必须要有

struct edge{

    //边的两个端点编号 
    int u,v;

    //边权 
    int cost; 

}E[MAXE]; 



//需要写一个排序函数来让数组E按边权从小到大排序,
//因此可以自定义sort的cmp函数

bool cmp(edge a,edge b) 
{

    return a.cost<b.cost;

}



//kruskal算法伪代码模板


int kruskal() 
{
    令最小生成树的边权之和为ans、最小生成树的当前边数 num_edge;

    将所有边按边权从小到大排序;

    for( 从小到大枚举所有边  ) 
    {
        if( 当前测试边的两个端点在不同的连通块中  )
        {
            将该测试边加入最小生成树中;

            ans+=测试边的边权;

            最小生成树的当前边数num_edge+1;

            当边数num_edge等于顶点数-1时结束循环; 


        }



    }





}




//伪代码中两处地方很不直观
//1.如何判断测试边的两个端点是否在不同的连通块中;
//2.如何将测试边加入最小生成树










输入

6 10
0 1 4
0 4 1
0 5 2
1 2 1
1 5 3
2 3 6
2 5 5
3 4 5
3 5 4
4 5 3

输出

11


  //以上问题需要用到并查集,下面 提供kruskal算法实际应用例程 #include <cstdio>  #include <algorithm> using namespace std; const int MAXV=110; const int MAXE=10010; //边集定义部分 struct edge{ //边的两个端点编号  int u,v; //边权 int cost; }E[MAXE]; bool cmp(edge a,edge b) { return a.cost<b.cost; } //并查集部分 //并查集数组  int father[MAXV]; //并查集查询函数 int find_father(int x) { int a=x; while(x!=father[x]) { x=father[x]; } //路径压缩 while( a!=father[a] ) { int z=a; a=father[a]; father[z]=x; } return x; } //kruskal 部分,返回最小生成树的边权之和,参数n为顶点个数, //m为图的边数 int kruskal(int n,int m) { //ans 为边权之和,num_edge为当前生成树的边数 int ans=0; int num_edge=0; for(int i=0;i<n;i++) { //初始化并查集  father[i]=i; } //所有边权按边权从小到大排序  sort(E,E+m,cmp); for(int i=0;i<m;i++) { //查询测试边两个端点所在集合的根结点  int fau=find_father(E[i].u); int fav=find_father(E[i].v); //如果不在一个集合中  if( fau!=fav ) { father[fau]=fav; //合并集合(就是把测试边加入到最小生成树中)  //边权之和增加测试边的边权  ans+=E[i].cost; //当前生成树的边树加1  num_edge++; //边树等于顶点数减1时结束算法  if( num_edge == n-1 ) { break; } } } //无法连通时返回-1  if( num_edge !=n-1 ) { return -1; } else { //返回最小生成数的边权之和  return ans; } } int main() { int n,m; //顶点数、边数  scanf("%d%d",&n,&m); for(int i=0;i<m;i++) { //两个端点编号,边权  scanf("%d%d%d",&E[i].u,&E[i].v,&E[i].cost); } int ans= kruskal(n,m); printf("%d\n",ans); return 0; }