Kruskal 算法的 C++ 实现
C++ implementation of Kruskal's algorithm
我正在尝试实现 Kruskal 算法。这是我正在使用的结构图:
g = 边数组,它保留了左端和右端以及边的权重;
c = 存储 conex 组件的数组; c[N] = 我们在其中找到第 N 个顶点的 conex 组件;
a = 存储 MST 的数组;
m = 顶点数;
n = nr 个节点。
以下代码有两个问题:
1) 对于以下输入,它输出 MST 的成本是 18(这是错误的,成本实际上是 14):
7 ( =m )
6 ( =n )
1 2 9
1 3 5
1 4 2
2 3 7
3 5 3
4 6 1
5 6 1
2) 一步一步编译代码没有报错,虽然程序实际执行的时候会在某个时候停止,我想是在打印MST成本的时候。
感谢您的帮助!这是代码:
#include<stdio.h>
#include<stdlib.h>
#define grafMAX 101
FILE *fin = fopen("grafin.txt","r");
FILE *fout = fopen("grafout.txt","w");
struct Vertex{
int first,last,Cost;
};
void read_graf(Vertex **g, int *c, int &m, int &n){
int x,y,w;
fscanf(fin,"%d%d",&m,&n);
*g = (Vertex *)malloc(m*sizeof(Vertex));
for(int i=1;i<=m;++i){
fscanf(fin,"%d%d%d",&x,&y,&w);
(*g+i)->first = x;
(*g+i)->last = y;
(*g+i)->Cost = w;
}
for(int i=1;i<=n;++i)
c[i] = i;
}
int costMST(Vertex *g, int *a, int n){
int MST = 0;
for(int i=1;i<n;++i)
MST += g[a[i]].Cost;
return MST;
}
void Kruskal(Vertex *g, int *c, int *a, int n){
int nr = 0, mini, maxi;
for(int i=1;nr<n-1;++i)
if(c[g[i].first] != c[g[i].last]){
a[++nr] = i;
if(c[g[i].first] < c[g[i].last]){
mini = c[g[i].first];
maxi = c[g[i].last];
}
else{
maxi = c[g[i].first];
mini = c[g[i].last];
}
for(int j=1;j<=n;++j)
if(c[j] == maxi)
c[j] = mini;
}
}
inline int cmp(const void *a, const void *b){
return (((Vertex *)a)->Cost - ((Vertex *)b)->Cost);
}
int a[grafMAX], c[grafMAX];
int main(){
Vertex *g;
int m, n;
read_graf(&g,c,m,n);
qsort(g,m,sizeof(Vertex),cmp);
Kruskal(g,c,a,n);
fprintf(fout,"The cost of the MST is: %d.\n",costMST(g,a,n));
fclose(fin);
fclose(fout);
return 0;
}
你的代码中有很多错误,我认为是因为你从 1 而不是 0 开始对顶点进行编号。其中一个错误导致它崩溃,我认为另一个错误导致了产生错误的结果。
我将所有内部编号更改为从 0 开始,这样就可以正常工作了。我重命名了你的变量,因为它们的命名非常荒谬(你所说的顶点是边)而且我无法像那样理解它们的代码。
恐怕我忘记了我更改的所有内容,但如果您将它与您的原始代码进行比较,我希望您能看到我所做的。
请注意,我添加了一些调试行。当你搞不懂你的代码在干什么的时候,只要打印相关的变量,你很快就会知道问题出在哪里了。
#include<stdio.h>
#include<stdlib.h>
#define grafMAX 101
FILE *fin = fopen("grafin.txt","r");
FILE *fout = fopen("grafout.txt","w");
struct Edge {
int first,last,Cost;
};
void read_graf(Edge **g, int *components, int &num_edges, int &num_vertices){
int x,y,w;
fscanf(fin,"%d %d",&num_edges,&num_vertices);
*g = (Edge *)malloc(num_edges*sizeof(Edge));
for(int i=0;i<num_edges;++i){
fscanf(fin,"%d %d %d",&x,&y,&w);
(*g+i)->first = x - 1;
(*g+i)->last = y - 1;
(*g+i)->Cost = w;
}
for(int i=0;i< num_vertices;++i)
components[i] = i;
}
int costMST(Edge *edges, int *answer, int num_edges){
int MST = 0;
for(int i=0;i<num_edges;++i)
MST += edges[answer[i]].Cost;
return MST;
}
void print_components(const int* components, int num_components)
{
for (int i = 0; i < num_components; i++) {
printf("Vertex %d is in component %d\n", i, components[i]);
}
putchar('\n');
}
void print_edge(const Edge& edge, int index)
{
printf("Edge %d connecting %d to %d with weight %d", index, edge.first, edge.last, edge.Cost);
}
void Kruskal(Edge *edges, int *components, int *answer, int num_edges, int num_vertices){
int nr = 0, mini, maxi;
for(int i=0;i<num_edges && nr < num_vertices - 1;++i) {
printf("Considering ");
print_edge(edges[i], i);
putchar('\n');
if(components[edges[i].first] != components[edges[i].last]){
printf("Adding ");
print_edge(edges[i], i);
putchar('\n');
answer[nr++] = i;
if(components[edges[i].first] < components[edges[i].last]){
mini = components[edges[i].first];
maxi = components[edges[i].last];
}
else{
maxi = components[edges[i].first];
mini = components[edges[i].last];
}
for(int j=0;j<num_vertices;++j)
if(components[j] == maxi)
components[j] = mini;
print_components(components, num_vertices);
}
else {
printf("Rejecting ");
print_edge(edges[i], i);
putchar('\n');
}
}
}
inline int cmp(const void *a, const void *b){
return (((Edge *)a)->Cost - ((Edge *)b)->Cost);
}
int answer[grafMAX], components[grafMAX];
int main(){
Edge *edges;
int num_edges, num_vertices;
read_graf(&edges,components,num_edges,num_vertices);
qsort(edges,num_edges,sizeof(Edge),cmp);
Kruskal(edges,components,answer,num_edges,num_vertices);
fprintf(fout,"The cost of the MST is: %d.\n",costMST(edges,answer,num_vertices - 1));
fclose(fin);
fclose(fout);
return 0;
}
我正在尝试实现 Kruskal 算法。这是我正在使用的结构图:
g = 边数组,它保留了左端和右端以及边的权重;
c = 存储 conex 组件的数组; c[N] = 我们在其中找到第 N 个顶点的 conex 组件;
a = 存储 MST 的数组;
m = 顶点数;
n = nr 个节点。
以下代码有两个问题:
1) 对于以下输入,它输出 MST 的成本是 18(这是错误的,成本实际上是 14):
7 ( =m )
6 ( =n )
1 2 9
1 3 5
1 4 2
2 3 7
3 5 3
4 6 1
5 6 1
2) 一步一步编译代码没有报错,虽然程序实际执行的时候会在某个时候停止,我想是在打印MST成本的时候。
感谢您的帮助!这是代码:
#include<stdio.h>
#include<stdlib.h>
#define grafMAX 101
FILE *fin = fopen("grafin.txt","r");
FILE *fout = fopen("grafout.txt","w");
struct Vertex{
int first,last,Cost;
};
void read_graf(Vertex **g, int *c, int &m, int &n){
int x,y,w;
fscanf(fin,"%d%d",&m,&n);
*g = (Vertex *)malloc(m*sizeof(Vertex));
for(int i=1;i<=m;++i){
fscanf(fin,"%d%d%d",&x,&y,&w);
(*g+i)->first = x;
(*g+i)->last = y;
(*g+i)->Cost = w;
}
for(int i=1;i<=n;++i)
c[i] = i;
}
int costMST(Vertex *g, int *a, int n){
int MST = 0;
for(int i=1;i<n;++i)
MST += g[a[i]].Cost;
return MST;
}
void Kruskal(Vertex *g, int *c, int *a, int n){
int nr = 0, mini, maxi;
for(int i=1;nr<n-1;++i)
if(c[g[i].first] != c[g[i].last]){
a[++nr] = i;
if(c[g[i].first] < c[g[i].last]){
mini = c[g[i].first];
maxi = c[g[i].last];
}
else{
maxi = c[g[i].first];
mini = c[g[i].last];
}
for(int j=1;j<=n;++j)
if(c[j] == maxi)
c[j] = mini;
}
}
inline int cmp(const void *a, const void *b){
return (((Vertex *)a)->Cost - ((Vertex *)b)->Cost);
}
int a[grafMAX], c[grafMAX];
int main(){
Vertex *g;
int m, n;
read_graf(&g,c,m,n);
qsort(g,m,sizeof(Vertex),cmp);
Kruskal(g,c,a,n);
fprintf(fout,"The cost of the MST is: %d.\n",costMST(g,a,n));
fclose(fin);
fclose(fout);
return 0;
}
你的代码中有很多错误,我认为是因为你从 1 而不是 0 开始对顶点进行编号。其中一个错误导致它崩溃,我认为另一个错误导致了产生错误的结果。
我将所有内部编号更改为从 0 开始,这样就可以正常工作了。我重命名了你的变量,因为它们的命名非常荒谬(你所说的顶点是边)而且我无法像那样理解它们的代码。
恐怕我忘记了我更改的所有内容,但如果您将它与您的原始代码进行比较,我希望您能看到我所做的。
请注意,我添加了一些调试行。当你搞不懂你的代码在干什么的时候,只要打印相关的变量,你很快就会知道问题出在哪里了。
#include<stdio.h>
#include<stdlib.h>
#define grafMAX 101
FILE *fin = fopen("grafin.txt","r");
FILE *fout = fopen("grafout.txt","w");
struct Edge {
int first,last,Cost;
};
void read_graf(Edge **g, int *components, int &num_edges, int &num_vertices){
int x,y,w;
fscanf(fin,"%d %d",&num_edges,&num_vertices);
*g = (Edge *)malloc(num_edges*sizeof(Edge));
for(int i=0;i<num_edges;++i){
fscanf(fin,"%d %d %d",&x,&y,&w);
(*g+i)->first = x - 1;
(*g+i)->last = y - 1;
(*g+i)->Cost = w;
}
for(int i=0;i< num_vertices;++i)
components[i] = i;
}
int costMST(Edge *edges, int *answer, int num_edges){
int MST = 0;
for(int i=0;i<num_edges;++i)
MST += edges[answer[i]].Cost;
return MST;
}
void print_components(const int* components, int num_components)
{
for (int i = 0; i < num_components; i++) {
printf("Vertex %d is in component %d\n", i, components[i]);
}
putchar('\n');
}
void print_edge(const Edge& edge, int index)
{
printf("Edge %d connecting %d to %d with weight %d", index, edge.first, edge.last, edge.Cost);
}
void Kruskal(Edge *edges, int *components, int *answer, int num_edges, int num_vertices){
int nr = 0, mini, maxi;
for(int i=0;i<num_edges && nr < num_vertices - 1;++i) {
printf("Considering ");
print_edge(edges[i], i);
putchar('\n');
if(components[edges[i].first] != components[edges[i].last]){
printf("Adding ");
print_edge(edges[i], i);
putchar('\n');
answer[nr++] = i;
if(components[edges[i].first] < components[edges[i].last]){
mini = components[edges[i].first];
maxi = components[edges[i].last];
}
else{
maxi = components[edges[i].first];
mini = components[edges[i].last];
}
for(int j=0;j<num_vertices;++j)
if(components[j] == maxi)
components[j] = mini;
print_components(components, num_vertices);
}
else {
printf("Rejecting ");
print_edge(edges[i], i);
putchar('\n');
}
}
}
inline int cmp(const void *a, const void *b){
return (((Edge *)a)->Cost - ((Edge *)b)->Cost);
}
int answer[grafMAX], components[grafMAX];
int main(){
Edge *edges;
int num_edges, num_vertices;
read_graf(&edges,components,num_edges,num_vertices);
qsort(edges,num_edges,sizeof(Edge),cmp);
Kruskal(edges,components,answer,num_edges,num_vertices);
fprintf(fout,"The cost of the MST is: %d.\n",costMST(edges,answer,num_vertices - 1));
fclose(fin);
fclose(fout);
return 0;
}