Kruskal

Prim算法用来处理稠密图,Kruskal算法来处理稀疏图。

大致思路:

先用结构体对该的边以及点进行储存,然后根据每条边的权重来进行升序排序,
取权重最小的边放入所要维护的树中:如果该条边不在区域中才会将其放入区域中(所要维护的树中)。判断是否在区域中的方法即是:运用并查集的查找函数,用于找到顶点x所在的集合的代表元素,如果根节点相同,那么就在同一片区域中(所要维护的树中)

伪代码:

for(int i=0;i<m;i++)
{
  if(find(a)!=find(b))
{
p[find(a)]=find(b);
对应的其它条件
}

}

代码:

/*
①将所有边按权重从小到大排序
②枚举每条边a,b权重c
  if(a,b不连通的话)
   将这条边加入集合当中去
*/

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N=1e5+10;
//ans表示最小生成树的权值,cnt表示最小生成树的边数(若要表示点数,cnt的初始值应该=1)
int n,m,cnt,ans;
int p[N];

struct Edge
{
    int a,b,w;
//重载运算符,使得该结构体可以以边的权重来排序
    bool operator< (const Edge &W)const
    {
        return w<W.w;
    }
}edge[N*2];

/*
寻找该点的祖宗节点(这是并查集里的板子)
并查集的查找函数,用于找到顶点x所在的集合的代表元素,并进行路径压缩。
*/
int find(int x)
{
    if(p[x]!=x) p[x]=find(p[x]);
    return p[x];
}

void kruskal()
{
    for(int i=0;i<m;i++)
    {
        //取出每条边对应的点以及权值
        int a=edge[i].a,b=edge[i].b,c=edge[i].w;
        //如果两点不在同一区域上的话
        /*
        如果此时在同一区域上,则会有两种可能:①:已经放入区域了,不需要重复放入
        ②:将此点放入区域后恰好使区域形成环(也就是①的特例)
        */
        if(find(a)!=find(b))
        {
            //置为同一区域
            p[find(a)]=find(b);
            //对应区域的权值增加
            ans+=c;
            //区域边数增加
            cnt++;
        }
    }
    
    //n个点对应n-1条边
    if(cnt<n-1) cout << "impossible";
    else cout << ans;
}

int main()
{
    cin >> n >> m;
    
    //初始化并查集
    for(int i=1;i<=n;i++) p[i]=i;
    
    for(int i=0;i<m;i++)
    {
        int a,b,c;
        cin >> a >> b >> c;
        edge[i]={a,b,c};
    }
    //排序,对边的权值进行排序
    sort(edge,edge+m);
    
    kruskal();
    
    return 0;
}

重载运算符:

若想比较边的权重:

bool operator< (const Edge &W) const
{
    return w<W.w;
}
//上述Edge表示结构体名,W表示重载结构体

 若想比较点的大小:

struct Edge {
    int a, b, w;
    
    // 重载<运算符,首先按照a升序排序,如果a相同,则按照b升序排序
    bool operator< (const Edge &W)const {
        if (a == W.a) {
            return b < W.b;
        }
        return a < W.a;
    }
};

在这个重载的运算符中,我们首先比较两个边的第一个点a。如果a相同,我们再比较第二个点b。这样,当我们对Edge类型的数组使用sort函数时,它会首先按照a进行升序排序,如果a相同,则按照b进行升序排序。

若想进行降序:

struct Edge {
    int a, b, w;
    
    // 重载<运算符,首先按照a升序排序,如果a相同,则按照b降序排序
    bool operator< (const Edge &W)const {
        if (a == W.a) {
            return b > W.b; // 注意这里改为>,表示降序
        }
        return a < W.a;
    }
};

 

此外:

在C++中,当你重载一个成员函数(比如运算符)时,通常你会看到&符号,这代表函数的引用调用。对于重载的运算符,使用&可以避免不必要的复制,尤其是在处理较大的结构体时。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值