最小生成树(1)——kruskal算法//SDNU1218

第一行国际惯例——咕咕咕。

本代码以sdnu1218为例

1.类似贪心的策略,先对边按权值进行排序,不停的选择最优边进行构建树
2.在构建过程中需要判断是否有环(并查集判断(如果不会并查集(我改天再补一下并查集博客
3.忽略我特别丑的代码风格
4.可以增加优化(在kruskal函数的循环里加一个提前跳出的操作,当边的个数>n-1时跳出即可(n为点的个数(最小生成树最多n-1条边(此处略过
5.时间复杂度与边的个数有关(适合稀疏图
6.先写kruskal是因为我prim不会写(这个晚上看了2/3时间的prim都不会写(我果然菜的很

这个题是最小生成树而不是最短路是因为它起点不固定的情况下遍历所有点且每条路只能走一次

#include <iostream>
#include <cstdio>
#include <algorithm>
#define inf 999999999999
#define maxn 200005
using namespace std;

int fa[maxn];
int n,m;
struct tree
{
    int u;
    int v;
    int cost;
} t[maxn];//用于存每条边

void init()
{
    for(int i=0; i<maxn; ++i)
    {
        t[i].cost=inf;
        fa[i]=i;
    }
}//初始化所有的权值为max,所有的父节点为其本身

bool com(tree x,tree y)
{
    if(x.cost<y.cost)
        return true;
    else
        return false;
}//按权值从小到大排序

int tofind(int x)
{
    while(fa[x]!=x)
    {
        x=fa[x];
    }
    return x;
}//找到每个点的父节点

void tojoin(int x,int y)
{
    x=tofind(x);
    y=tofind(y);
    if(x!=y)
        fa[x]=y;
}//合并两棵树

int kruskal()
{
    int ans=0;
    for(int i=0; i<m; ++i)
    {
        int u=t[i].u;
        int v=t[i].v;
        if(tofind(u)==tofind(v))
            continue;//当两个点的父节点为同一节点(即早已联通,下一个循环
        ans+=t[i].cost;
        tojoin(u,v);//合并两个为同一个棵树
    }
    return ans;
}
int main()
{
    init();
    scanf("%d%d",&n,&m);
    for(int i=0; i<m; ++i)
    {
        int u,v,cost;
        scanf("%d%d%d",&t[i].u,&t[i].v,&t[i].cost);
    }//将每个边储存
    sort(t,t+m,com);//排序
    printf("%d\n",kruskal());
    return 0;
}

//后期应该会更新几个练习题

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值