最小生成树 (Minimum Spanning Tree,MST) ---Kruskal算法

引导问题:

  假设要在N个城市之间建立通信联络网,则连通N个城市只需要N - 1条线路。这时,自然会考虑这样一个问题,如何在最省经费的前提下建立这个通信网。

基于问题所建立的定义:

  可以用联通网来表示N个城市以及N个城市之间可能设置的连通线路,其中网的顶点表示城市,边表示两城市之间的线路,赋予边的权值表示相应的代价。对于N个顶点的连通网可以建立许多不同的生成树,每一棵生成树都可以是一个通信网。现在,要选择这样一颗生成树,也就是使总的耗费最少,这个问题就是构造连通网的的最小代价生成树的问题,即最小生成树问题。一颗生成树的代价就是树上各边的代价之和。

算法:

  假设;连通网N = (V, {E}),则令最小生成树的初始状态为只有N个顶点而无边的非连通图T = (V, {}),图中每个顶点自成一个连通分量。在E中选择代价最小的边,若该边依附的顶点落在不同的连通分量上,则将该边加入到T中,否则舍去此边,选择下一条代价最小的边。以此类推,直至所有顶点都在同一个连通分量上为止。

用图来描述:

初始图 N                      初始图 T

   

求此图的最小生成树。

第一步:先给这些边排序。

然后选择第(1)条边V1 -- V4,第一条边的两端属于两个连通分量,所以可以加入 T 中

继续选择第(2)条边V5 -- V3,第二条边的两端也属于两个连通分量,所以也可以加入 T 中

选择第(3)条边V4 -- V6,第三条边的两端也属于两个连通分量,加入 T 中

选择第四条边V1 -- V7,同样属于两个连通分量,加入 T 中

选择第五条边,V2 -- V5,也属于两个连通分量,加入 T 中

选择第六条边V2 -- V3后会变成这样

很明显,第六条边的两端是属于一个连通分量的,所以舍弃继续选择第七条边V5 -- V6

同样,第七条边的两端属于同一个连通分量,所以舍弃,选择第八条变条边V2 -- V4

和上面两条边的状况一样,所以继续舍弃,选择第九条边,V5 -- V7

到此为止,所有的点都被连通到了一起,图中仅存在一个连通分量,算法停止,T 中所选择的边和原先的点构成的图就是要找的最小生成树。

具体实现:

  判断是否属于一个连通分量可以用并查集实现。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
using namespace std;

const int MAXN = 2e3+ 3;
int pre[MAXN];
int m,n;

int Find(int x)     //并查集
{
    return x == pre[x] ? x :(pre[x] = Find(pre[x]));
}

struct Node   //储存数据
{
    int u, v, w;
}cy[103];

int mycmp(Node a,Node b)
{
    return a.w < b.w;
}

void mst()
{
    for(int i = 0 ; i < 102; i++)
        pre[i] = i;
}

int kru()
{
    int ans = 0;
    int cnt = 0;
    sort(cy + 1, cy + n + 1, mycmp);  //对边进行升序排序
    for(int i = 1; i <= n; i++)       //从最小的那条边开始寻找
    {
        int fv = Find(cy[i].v);
        int fu = Find(cy[i].u);
        if(fv != fu)               //如果不属于同一个连通分量就把当前这条比较小的边加进去
        {
            pre[fv] = fu;
            ans += cy[i].w;
            cnt ++;
        }
        if(cnt == m -1)      //构成了最小生成树
        {
            return ans;
            break;
        }
    }
    return -1;
}

int main()
{
    //freopen("in.cpp","r",stdin);
    while(~scanf("%d%d",&n,&m) && n)
    {
        mst();
        for(int i = 1; i <= n; i++)
            scanf("%d%d%d",&cy[i].u, &cy[i].v, &cy[i].w);
        int ans = kru();
        if(ans != -1)
            printf("%d\n",ans);
        else
            printf("?\n");
    }
    return 0;
}
时间: 2024-10-25 12:20:19

最小生成树 (Minimum Spanning Tree,MST) ---Kruskal算法的相关文章

【算法】关于图论中的最小生成树(Minimum Spanning Tree)详解

喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 本节纲要 什么是图(network) 什么是最小生成树 (minimum spanning tree) 最小生成树的算法 什么是图(network)? 这里的图当然不是我们日常说的图片或者地图.通常情况下,我们把图看成是一种由"顶点"和"边"组成的抽象网络.在各个"顶点"间可以由"边"连接起来,使两个顶点间相互关联起来.图的结构可以描述多种复杂的数据对象,

HDOJ 题目4408 Minimum Spanning Tree(Kruskal+Matrix_Tree)

Minimum Spanning Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1408    Accepted Submission(s): 450 Problem Description XXX is very interested in algorithm. After learning the Prim algori

算法练习:最小生成树 (Minimum Spanning Tree)

(注:此贴是为了回答同事提出的一个问题而匆匆写就,算法代码只求得出答案为目的,效率方面还有很大的改进空间) 最小生成树是指对于给定的带权无向图,需要生成一个总权重最小的连通图.其问题描述及算法可以详见:https://en.wikipedia.org/wiki/Minimum_spanning_tree以下我选用其中一个简单的算法描述,编写 Python 代码尝试解决此问题. 下面是同事提出的问题的原图: 程序: 1 # coding: utf-8 2 3 from sets import Se

UVAlive3662 Another Minimum Spanning Tree 莫队算法

就是莫队的模板题 /* Memory: 0 KB Time: 1663 MS Language: C++11 4.8.2 Result: Accepted */ #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cstdlib> #include<cmath> using namespace std; typedef l

[思维]Minimum Spanning Tree

题目描述 In the mathematical discipline of graph theory, the line graph of a simple undirected weighted graph G is another simple undirected weighted graph L(G) that represents the adjacency between every two edges in G. Precisely speaking, for an undire

Geeks : Kruskal’s Minimum Spanning Tree Algorithm 最小生成树

寻找图中最小连通的路径,图如下: 算法步骤: 1. Sort all the edges in non-decreasing order of their weight. 2. Pick the smallest edge. Check if it forms a cycle with the spanning tree formed so far. If cycle is not formed, include this edge. Else, discard it. 3. Repeat st

【HDU 4408】Minimum Spanning Tree(最小生成树计数)

Problem Description XXX is very interested in algorithm. After learning the Prim algorithm and Kruskal algorithm of minimum spanning tree, XXX finds that there might be multiple solutions. Given an undirected weighted graph with n (1<=n<=100) vertex

HDU 4408 Minimum Spanning Tree 最小生成树计数

Minimum Spanning Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) [Problem Description] XXX is very interested in algorithm. After learning the Prim algorithm and Kruskal algorithm of minimum spanning tree, XXX

poj——2031 最小生成树(MST) Kruskal算法

poj——2031 最小生成树(MST)  Kruskal算法 Building a Space Station Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 4985   Accepted: 2503 Description You are a member of the space station engineering team, and are assigned a task in the constructio