最小生成树之kruskal算法(附代码)

prim算法是通过找距离最近的节点来扩充最小生成树的,稠密图选择prim算法效率比较高,但是对于稀疏图呢,prim算法就显的比较鸡肋了。对于稀疏图,有一个叫做kruskal的算法。此算法求稀疏图的效率比较高,时间复杂度为O(ElogE)。

kruskal算法主要通过找最小的边来合并节点来一步步的生成树的,他一开始将每个节点看成一棵树,然后通过边的关系来进行节点的合并,这里需要对给出的边进行升序排序,然后再检查边所联系的两个节点是否在同一集合,如果不在同一集合则将两个集合合并,直到整个森林变为一颗树为止。

代码如下:
 

#include 
#include 
#include 
#include 
#include 
using namespace std;
const int maxn=1005;
int n,m;
struct edge
{
    int s,e;
    int len;
};
edge e[maxn];
int a[maxn];
vector  ve; //记录纳入的边
//初始化
int init ()
{
    for (int i=1;i<=n;i++)
        a[i]=i;
}
//查找父节点
int finds(int re)
{
    if(re==a[re])
        return re;
    return a[re]=finds(a[re]);
}
//将两个集合联合
bool unit (int x,int y)
{
    int temp1=finds(x);
    int temp2=finds(y);
    if(temp1!=temp2)
    {
         a[temp1]=temp2;
         return true;
    }
    return false;
}
int compare (edge a,edge b)
{
    return a.len1;i++)
    {
        //判断是否在同一集合中,在同一集合就不再计入
        if(unit(e[i].s,e[i].e))
        {
            ve.push_back(e[i]);
            sum+=e[i].len;
            num--;
        }
    }
    if(num==1)
        printf("最小生成树的权值和为%d\n",sum);
    else
        printf("不存在最小生成树\n");
}
//遍历纳入的边
void traverse ()
{
    printf("纳入的边为:\n");
    for (int i=0;i%d 长度为%d\n",ve[i].s,ve[i].e,ve[i].len);
}
int main()
{
    scanf("%d%d",&n,&m);
    init();
    for (int i=0;i5 长度为1
3<->6 长度为1
1<->6 长度为2
2<->5 长度为2
2<->4 长度为6*/

 

你可能感兴趣的:(基本算法与数据结构)