#include <cstdio>
#include <cstdlib>
#include <string>
#include <iostream>
#include <conio.h>
#include <locale>
using namespace std;
const int countMax = 50;
FILE * inputFile, * outputFile;
struct edgeStruct {
int u, v, weight; // ребро (u, v), weight - вес ребра
};
int SortBase(int p, int r, edgeStruct E[]) {
int i, j;
edgeStruct x {}, tmp {};
i = p - 1;
j = r + 1;
x = E[p + rand() % (r - p + 1)];
while (true) {
do {
i++;
} while (E[i].weight < x.weight);
do {
j--;
} while (E[j].weight > x.weight);
if (i < j) {
tmp = E[i];
E[i] = E[j];
E[j] = tmp;
} else break;
}
return j;
}
void SortByWeightAsc(int p, int r, edgeStruct E[]) {
int q;
if (p >= r) return;
q = SortBase(p, r, E);
SortByWeightAsc(p, q, E);
SortByWeightAsc(q + 1, r, E);
}
/* Алгоритм Краскала с использованием систем непересекающихся множеств */
void DoKruskal(edgeStruct E[], int N, int M) {
int i, j, r1, r2;
int r[countMax + 1]; // представители множеств
int treeWeight;
// сначала имеем N множеств, в каждом по одной вершине,
// которая является представителем своего множетсва
for (i = 1; i <= N; i++) {
r[i] = i;
}
SortByWeightAsc(1, M, E); // сортировка ребер по возрастанию весов
treeWeight = 0; // вес минимального остовного дерева
for (i = 1; i <= M; i++) { //цикл по ребрам в порядке возрастания весов
// если вершины ребра принадлежат разным множествам, то
// объединяем эти множества
if (r[E[i].u] != r[E[i].v]) {
// выводим новое ребро дерева
fprintf(outputFile, "( %d, %d ) : %d\n", E[i].u - 1, E[i].v - 1, E[i].weight);
treeWeight += E[i].weight; // пересчитываем вес дерева
// объединяем множества
r1 = r[E[i].u];
r2 = r[E[i].v];
for (j = 1; j <= N; j++) {
if (r[j] == r1)
r[j] = r2;
}
}
}
// выводим вес полученного дерева
fprintf(outputFile, "Ves: %d\n", treeWeight);
}
int main() {
setlocale(LC_ALL, "rus");
system("cls");
auto outputFileName = const_cast < char * > ("output.txt");
char c = 'y';
while (c != 'n') {
char inputFileName[50];
system("cls");
cout << "Программа для нахождения остова минимального веса" << endl;
cout << "Введите имя файла: ";
cin >> inputFileName;
if (inputFileName != nullptr) {
int N, M, i, j, weight;
edgeStruct E[countMax * countMax + 1];
inputFile = fopen(inputFileName, "r");
if (inputFile != nullptr) {
outputFile = fopen(outputFileName, "w");
N = 7;
M = 0;
for (i = 1; i <= N; i++) {
for (j = 1; j <= N; j++) {
fscanf(inputFile, "%d", & weight);
if (weight > 0) {
M++;
E[M].u = i;
E[M].v = j;
E[M].weight = weight;
}
}
}
cout << "Результаты работы программы сохранены в файл" << outputFileName << endl;
fprintf(outputFile, "Остов минимального веса:\n");
DoKruskal(E, N, M);
fclose(inputFile);
fclose(outputFile);
} else cout << "Ошибка: не удается прочитать файл" << endl;
} else cout << "Файл с таким именем не найден" << endl;
cout << endl;
cout << "Попробовать снова? (y/n): ";
c = static_cast < char > (getch());
cout << endl;
system("pause");
}
return 0;
}