<数据结构>kruskal算法求最小生成树(并查集版)

输入:
第一行为顶点数n和边数m
后面m行数据: 顶点 顶点 边上的权值
输出:按顺序输出Kruskal算法求得的最小生成树的边集,每行一条边:顶点 顶点 边上的权值,其中第一个顶点的编号应小于第二个顶点的编号。这个点卡了我好久,写代码之前要好好看看题目,不要一看Kruskal就把算法写出来,输出格式也要注意(算法没问题因为格式问题调试好久才是真的浪费时间…
先放AC过的代码:

#include<stdio.h>

#define MAXV 31
#define MAXE 101

typedef struct {
    int u,v;
    int weight;
}Edge;

Edge E[MAXE];

int father[MAXV];//并查集数组
int FindFather (int x);
void Kruskal (int n, int m);
void Sort (Edge E[],int m);

int main (void) {
    int n, m;
    scanf ("%d %d", &n, &m);
    int i;
    for (i=0; i < m; i++) {
        scanf ("%d %d %d", &E[i].u, &E[i].v, &E[i].weight);
    }
    Kruskal (n,m);
    return 0;
}

int FindFather (int x) {
    int a = x;
    while (x != father[x]) {
        x = father[x];
    }

    while (a != father[a]) {
        int z = a;
        a = father[a];
        father[z] = x;
    }

    return x;
}
void Kruskal (int n, int m) {
    int i, j, num = 0;
    
    if (n == 1) {
        printf ("%d %d %d\n", E[0].u, E[0].v, E[0].weight);
        return;
    }

    for (i = 0; i < n; i++) {
        father[i] = i;
    }

    Sort (E, m);
    int faU, faV;
    for (i = 0; i < m; i++) {
        faU = FindFather (E[i].u);
        faV = FindFather (E[i].v);
        if (faU != faV) {
            father[faU] = faV;
            num++;
            if (E[i].u > E[i].v) {
                printf ("%d %d %d\n",E[i].v, E[i].u, E[i].weight);
            }
            else {
                printf ("%d %d %d\n",E[i].u, E[i].v, E[i].weight);
            }
            

            if (num == n - 1) break;
        }
    }

    /*for (i = 0; i < m; i++) {
        printf ("%d ", E[i].weight);
    }*/
}

void Sort (Edge E[],int m) {
    int i, j;
    Edge t;
    for (i = 0; i < m; i++) {
        for (j = 0; j < m -i -1; j++) {
            if (E[j].weight > E[j + 1].weight) {
                t = E[j];
                E[j] = E[j + 1];
                E[j + 1] = t;
            }
        }
    }
}

算法主题来自《算法笔记》,然后做了些改动。毕竟《算法笔记》上的代码是C++的,sort函数之类的就不能用。

然后是我根据ppt上的伪码写的代码,5个测试点通过了3个,没有通过的原因还没有找到。有可能是我最近事情太多,脑子有点木,想不到哪种情况吧。也一并放上来,如果有大佬知道哪里有错误的话,还请指明,谢谢啦~

#include<stdio.h>
typedef struct {
	int u,v;//边的两个顶点
	int weight;//边的权值 
}Edge;

void Kruskal (Edge e[],int n);
void Sort_Edge (Edge e[], int n);
int main (void) {
	int n, m;//顶点数,边数
	scanf ("%d %d", &n, &m);
	int i, u, v, weight;
	Edge e[m];//从0开始 
	
	for (i = 0; i < m; i++) {//从0开始 ,以边数为界限而不是顶点 
		scanf ("%d %d %d", &u, &v, &weight);
		e[i].u = u;
		e[i].v = v;
		e[i].weight = weight; 
	}
	
	Sort_Edge (e,m);
	/*for (i = 0; i < m; i++) {
		printf ("%d %d %d\n", e[i].u, e[i].v, e[i].weight);
	}*/
	Kruskal (e,n);
	
	
	return 0;
}
//权值从小到大排列 
void Sort_Edge (Edge e[], int n) {
	int i,j;
	Edge temp;
	for (i = 0; i < n; i++) {
		for (j = 0; j < n - i - 1; j++) {
			if (e[j].weight > e[j + 1].weight) {
				temp = e[j];
				e[j] = e[j + 1];
				e[j + 1] = temp;
			}
		}
	}
}
void Kruskal (Edge e[],int n) {
	int i, j, k, su, sv;
	int Vset[n];
	for (i = 0; i < n; i++) {
		Vset[i] = i;
	}
	k = 1;//生成的边数 ,k=n-1时跳出 
	j = 0;
	while (k < n) {
		if (Vset[e[j].u] != Vset[e[j].v]) {
			if (e[j].u > e[j].v) {
                printf ("%d %d %d\n",e[j].v, e[j].u, e[j].weight);
            }
            else {
                printf ("%d %d %d\n",e[j].u, e[j].v, e[j].weight);
            }
			//printf ("%d %d %d\n", e[j].u, e[j].v, e[j].weight);
			k++;
			su = Vset[e[j].u];
			sv = Vset[e[j].v];
			
			for (i = 0; i < n; i++) {
			    if (Vset[i] == sv) {
			    	Vset[i] = su;
			    }
		    }
		}
		j++;	
	}
}

通过将顶点的值置为相同来表示边的加入。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值