记录一下最小生成树Kruskal算法的一个class

很容易超时的,会更新

#include<stdio.h>
#include<vector>
#include<stdlib.h>
#include<algorithm>
using namespace std;
//需要以上头文件
class MST//图的邻接表类
{
    private:
    typedef struct EDGE {
        int x, y, weight;
        EDGE(int a, int b, int c) :weight(c), x(a), y(b) {}
        EDGE() :weight(), x(), y() {}
        bool operator <(const EDGE& b)
            const {
            if (weight == b.weight)
                if (x == b.x) {
                    return y < b.y;
                }
                else return x < b.x;
            else
                return weight < b.weight;
        }
    }edge;//边类
    typedef struct POINT{
        int x, y, weight;
        struct POINT* next;
        POINT() :weight(), x(), y(), next() {}
        POINT(int a, int b, int c, POINT* next) :weight(c), x(a), y(b), next(next) {}
    }point;//点类
    vector<point*> Point;//点集
    vector<int> per;//并查集
    vector<edge> Edge;//边集
    point* PointCreat()//分配点的内存
    {
        point* s = (point*)malloc(sizeof(point));
        s->next = NULL;
        return s;
    }
    void PointBuilt(int n)//0到n点初始化
    {
        for(int i=0;i<=n;i++){
        point *s=PointCreat();
        *s=point(0,0,0,NULL);
        Point.push_back(s);
        }
    }
    void PointClear(int n)//0到n点清空
    {
        point *tt;
        for (int i = 0; i <= n; i++){
            tt=Point[i];
            listClear(tt);
            Point[i]=PointCreat();
            *Point[i]=point(0,0,0,NULL);
        }
    }
    void listClear(point* x)//清空辅助
    {
        if (x == NULL) return;
        if (x->next != NULL) {
            listClear(x->next);
        }
        free(x);
    }
    void UnionBuilt(int n)//0到n并查集初始化
    {
        for (int i = 0; i <= n; i++) {
            per.push_back(i);
        }
    }
    void UnionClear(int n)//0到n并查集清空
    {
        per.clear();
    }
    void UnionConnect(int x, int y)//把x所在集合连到y
    {
        x = Find(x);
        y = Find(y);
        if (x != y){
            per[x] = y;
        }
    }
public:
        void Minimum_spanning_tree(){
        sort(Edge.begin(), Edge.end());
        while (!Edge.empty()){
            if (Find(Edge[0].x) != Find(Edge[0].y))
            {
                PointConnect(Edge[0].x, Edge[0].y, Edge[0].weight, 1);
            }
     Edge.erase(Edge.begin());
        }
    }
    void built(int n)//初始化n阶图
    {
        UnionBuilt(n);
        PointBuilt(n);
        Edge.clear();
        weight=0;
    }
   void Edgepush(int x, int y, int q)//输入边
    {
       Edge.push_back(edge(x, y, q));
    }
    void clear(int n)//清空n阶图
    {
        PointClear(n);
        UnionClear(n);
        Edge.clear();
    }
    int Find(int x)//并查集用
    {
        if (per[x] != x) x = Find(per[x]);
        else return x;
        return x;
    }
    int weight;
     void PointConnect(int from, int to, int weight, int mode)//根据边集连接点,mode=1有向
    {
        UnionConnect(from,to);
        point* s = PointCreat();
        point* t = Point[from];
        *s = point(from, to, weight, t->next);
        t->next = s;
        if (mode)PointConnect(to, from, weight, 0);
    }
  void getweight(int before, int now)
    {
        point* K = Point[now];
        if (K == NULL) return;
        K = K->next;
        while (K != NULL){
            if (K->y != before){
                weight += K->weight;
                getweight(now, K->y);
            }
            K = K->next;
        }
    }
};

外部接口

Minimum_spanning_tree() //生成最小生成树。
built(int n) //初始化(赋予内存)//没新建就使用一定有bug。
clear(int n) //清空所有(释放内存)//释放完要再新建。
Edgepush(int x, int y, int q) //输入边。
Find(int x) //连通分支查找,同连通分支返回值相同。
PointConnect(int from, int to, int weight, int mode)//根据边集连接点mode=1有向,mode=0无向。//图类外部接口,其实求生成树的时候没有用
getweight(0,0)//求树的权重/
int weight;//权重。

2021/5/29
数组版本来了,速度会更快。
删除了built方法,宏定义了点和边的最大个数,并且更新了求最小生成树中两点中的花费方法。
2021/5/30
修改了Minimum_spanning_tree(),增加了对能否生成最小生成树的判断。
修改了clear方法,现在从clear输入边和点的个数,其他方法都不用带上点或边的个数了。
将边数设为外部接口,方便临时修改。
新增 bool isUniqueMST()方法,判断最小生成树是否唯一。

#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
using namespace std;
#define MaximumOfPoint 1000
#define MaximumOfEdge   100005
class MAP//图的邻接表类
{
private:
    typedef struct EDGE{
        int x, y, weight;
        bool use;
        EDGE(int a, int b, int c) :weight(c), x(a), y(b),use(false) {}
        EDGE() :weight(), x(), y(),use() {}
        bool operator <(const EDGE& b)
            const {
            if (weight == b.weight)
                if (x == b.x){
                    return y < b.y;
                }
                else return x < b.x;
            else
                return weight < b.weight;
        }
    }edge;//边类
    typedef struct POINT{
        int x, y, weight;
        struct POINT* next;
        POINT() :weight(), x(), y(), next() {}
        POINT(int a, int b, int c, POINT* next) :weight(c), x(a), y(b), next(next) {}
    }point;//点类
    point* Point[MaximumOfPoint];//点集
    int per[MaximumOfPoint];//并查集
    point* PointCreat(){
        point* s = (point*)malloc(sizeof(point));
        s->next = NULL;
        return s;
    }//分配点的内存
    int Unionsum;
    void PointClear(){
        point* tt;
        for (int i = 0; i <= Pointsum; i++){
            tt = Point[i];
            listClear(tt);
            Point[i] = PointCreat();
            *Point[i] = point(0, 0, 0, NULL);
        }
    }//0到n点清空
    void listClear(point* x){
        if (x == NULL) return;
        if (x->next != NULL){
            listClear(x->next);
        }free(x);
    }//清空辅助
    void UnionConnect(int x, int y){
        x = Find(x);
        y = Find(y);
        if (x != y){
            per[x] = y;
            Unionsum--;
        }
    }//把x所在集合连到y
    int getCost(int aim,int before,int now,int i){
        point* K = Point[now];
        if (K == NULL ) return 0;
        if (now == aim) return 1;
        K = K->next;
        while (K != NULL){
            if (K->y != before){
                if(getCost(aim,now,K->y,i)){
                    maxCost=max(maxCost,K->weight);
                    minCost=min(minCost,K->weight);
                    totalCost+=K->weight;
                    return 1;
                }
            }K = K->next;
        }
    }
    void getWeight(int before, int now,int i){
        point* K = Point[now];
        if (K == NULL) return;
        K = K->next;
        while (K != NULL){
            if (K->y != before){
                Weight += K->weight;
                getWeight(now, K->y,i);
            }
            K = K->next;
        }
    }
    int Pointsum;
public:
    int Edgesum;
        int Weight;
        edge Edge[MaximumOfEdge];//边集
    bool Minimum_spanning_tree(){
        sort(Edge, Edge + Edgesum);
        int i = 0;
        while (i < Edgesum){
            if (Find(Edge[i].x) != Find(Edge[i].y)){
                PointConnect(Edge[i].x, Edge[i].y, Edge[i].weight, 1);
                Weight += Edge[i].weight;
                Edge[i].use=true;
            }i++;
        }
        return (Unionsum==1)?true:false;//若不能生成返回false
    }
    bool isUniqueMST(){
        for(int i=0;i<Edgesum;i++){
            if(Edge[i].use==false){
                getCost(Edge[i].x,Edge[i].y);
                if(maxCost>=Edge[i].weight) return false;
            }
        }
        return true;
    }
    void clear(int n,int m){//
        Pointsum=n;Edgesum=m;Unionsum=n;
        memset(Edge,0,sizeof(Edge));
        for (int i = 0; i <= Pointsum; i++){
            Weight = 0;maxCost=0;totalCost=0;minCost=0;
            point* tt;
            per[i] = i;
            tt = Point[i];
            listClear(tt);
            Point[i] = PointCreat();
            *Point[i] = point(0, 0, 0, NULL);
        }
    }//清空n阶图
   int Find(int x){
        int tt =x;
        while(x!=per[x]) x=per[x];
        while(tt!=x){
            int t=per[tt];
            per[tt]=x;
            tt=t;
        }
        return x;
    }//并查集用
    void PointConnect(int from, int to, int weight, int mode){
        UnionConnect(from,to);
        point* s = PointCreat();
        point* t = Point[from];
        *s = point(from, to, weight, t->next);
        t->next = s;
        if (mode)PointConnect(to, from, weight, 0);
    }//根据边集连接点,mode=1有向
    void Edgepush(int x, int y, int q,int i){
       Edge[i]=(edge(x, y, q));
    }
    void getWeight(int now){
        Weight=0;
        getWeight(now,now,1);
    }
    int totalCost;
    int maxCost;
    int minCost;
    int getCost(int from,int aim){
        totalCost=0;
        maxCost=0;
        minCost=2147483647;//MAXINT
        getCost(aim,from,from,1);
    }
};

外部接口
没写返回值都默认是void

bool Minimum_spanning_tree() //生成最小生成树(Kruskal算法)//能生成返回true不能false。
clear(int n,int m) //清空 n个点和所有边
Edgepush(int x, int y, int q,int i) //输入边。
int Find(int x) //连通分支查找,同连通分支返回值相同//图类外部接口,其实求生成树的时候没有用
PointConnect(int from, int to, int weight, int mode) //根据边集连接点mode=1有向,mode=0无向。 //图类外部接口,其实求生成树的时候没有用
getWeight(int now)//求树的权重 //保证now 是图中一点
getCost(int from,int aim) //得到图中从from到aim的点的总花费,最大最小花费
bool isUniqueMST() //判断最小生成树是否唯一//唯一true//不唯一false
int Weight;//权重。
int totalCost; //总花费
int maxCost;int minCost; //最大最小花费
int Edgesum//边数

2021/12/1

#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
using namespace std;
#define MaximumOfPoint 1000
#define MaximumOfEdge   100005
class MAP//图的邻接表类
{
private:
    typedef struct EDGE{
        int x, y, weight;
        bool use;
        EDGE(int a, int b, int c) :weight(c), x(a), y(b),use(false) {}
        EDGE() :weight(), x(), y(),use() {}
        bool operator <(const EDGE& b)
            const {
            if (weight == b.weight)
                if (x == b.x){
                    return y < b.y;
                }
                else return x < b.x;
            else
                return weight < b.weight;
        }
    }edge;//边类
    typedef struct POINT{
        int x, y, weight;
        struct POINT* next;
        POINT() :weight(), x(), y(), next() {}
        POINT(int a, int b, int c, POINT* next) :weight(c), x(a), y(b), next(next) {}
    }point;//点类
    point* Point[MaximumOfPoint];//点集
    int    per[MaximumOfPoint];//并查集
    point* PointCreat(){
        point* s = (point*)malloc(sizeof(point));
        s->next = NULL;
        return s;
    }//分配点的内存
    int Unionsum;
    void PointClear(){
        point* tt;
        for (int i = 0; i <= Pointsum; i++){
            tt = Point[i];
            listClear(tt);
            Point[i] = PointCreat();
            *Point[i] = point(0, 0, 0, NULL);
        }
    }//0到n点清空
    void listClear(point* x){
        if (x == NULL) return;
        if (x->next != NULL){
            listClear(x->next);
        }free(x);
    }//清空辅助
    void UnionConnect(int x, int y){//并查集用
        x = Find(x);
        y = Find(y);
        if (x != y){
            per[x] = y;
            Unionsum--;
        }
    }//把x所在集合连到y
    int getCost(int aim,int before,int now,int i){//获得aim到before 的费用
        point* K = Point[now];
        if (K == NULL ) return 0;
        if (now == aim) return 1;
        K = K->next;
        while (K != NULL){
            if (K->y != before){
                if(getCost(aim,now,K->y,i)){
                    maxCost=max(maxCost,K->weight);
                    minCost=min(minCost,K->weight);
                    totalCost+=K->weight;
                    return 1;
                }
            }K = K->next;
        }
    }
    int Pointsum;
    void PointConnect(int from, int to, int weight,int i){
        UnionConnect(from,to);
        point* s = PointCreat();
        point* t = Point[from];
        *s = point(from, to, weight, t->next);
        t->next = s;
        if (i)PointConnect(to, from, weight,0);//
    }//根据边集连接点,mode=1有向
    void getWeight(int before, int now,int i){
        Weight=0;
        point* K = Point[now];
        if (K == NULL) return;
        K = K->next;
        while (K != NULL){
            if (K->y != before){
                Weight += K->weight;
                getWeight(now, K->y,i);
            }
            K = K->next;
        }
    }
    void printree(int before,int now,int deep)
    {
        point *K=Point[now];
        K=K->next;
        if(K==NULL) return;
        {
            while(K!=NULL){
                if(K->y!=before){int n=deep;
                    while(n--)
                    {
                        printf("-");
                    }
                    printf("%d\n",K->y);
                    printree(now,K->y,deep*2);
                }
                K=K->next;
            }
        }
    }
public:
    int Edgesum;
    int mode;
    int Weight;
    edge Edge[MaximumOfEdge];//边集
    bool built_Minimum_spanning_tree(int true_is_directed){
        mode=true_is_directed;
        sort(Edge, Edge + Edgesum);
        int i = 0;
        while (i < Edgesum){//这是Kruskal算法
            if (Find(Edge[i].x) != Find(Edge[i].y)){//用并查集判断两个点是否在同一个集合
                PointConnect(Edge[i].x, Edge[i].y, Edge[i].weight,1);//连接两个点,在
                Weight += Edge[i].weight;
                Edge[i].use=true;
            }i++;
        }
        return (Unionsum==1)?true:false;//若不能生成返回false
    }
    bool isUniqueMST(){//最小生成树是否唯一
        for(int i=0;i<Edgesum;i++){
            if(Edge[i].use==false){
                getCost(Edge[i].x,Edge[i].y);
                if(maxCost>=Edge[i].weight) return false;
            }
        }
        return true;
    }
    void GetMap(int n){//
        Pointsum=n;Edgesum=0;Unionsum=n;
        memset(Edge,0,sizeof(Edge));
        for (int i = 0; i <= Pointsum; i++){
            Weight = 0;maxCost=0;totalCost=0;minCost=0;
            point* tt;
            per[i] = i;
            tt = Point[i];
            listClear(tt);
            Point[i] = PointCreat();
            *Point[i] = point(0, 0, 0, NULL);
        }
    }//清空n阶图
   int Find(int x){
        int tt =x;
        while(x!=per[x]) x=per[x];
        while(tt!=x){
            int t=per[tt];
            per[tt]=x;
            tt=t;
        }
        return x;
    }//并查集用
    void Edgepush(int x, int y, int q){
       Edge[Edgesum++]=(edge(x, y, q));
    }
    void getWeight(int now){//获取权重
        Weight=0;
        getWeight(now,now,1);
    }
    void printree()
    {
        printf("0\n");//只从编号为0的点输出,树是孩子兄弟链结构
        printree(0,0,1);
    }
    int totalCost;
    int maxCost;
    int minCost;
    int getCost(int from,int aim){
        totalCost=0;
        maxCost=0;
        minCost=2147483647;//MAXINT
        getCost(aim,from,from,1);
    }
};//图生成后还可以修改
int main()
{
    MAP A;
    int n,m;
    scanf("%d%d",&n,&m);
    int x,y,c;
        A.GetMap(n);

    for(int i=0;i<m;i++)
    {
        scanf("%d%d%d",&x,&y,&c);
        A.Edgepush(x,y,c);
    }
    A.built_Minimum_spanning_tree(1);
    printf("其最小生成树为\n");

    A.printree();
}
/*
6 8
0 1 9
0 2 10
1 2 7
1 3 5
2 4 6
2 5 7
3 4 11
4 5 8
*/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值