输入:
第一行为顶点数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++;
}
}
通过将顶点的值置为相同来表示边的加入。