nihonium
/
mipt_clang
Archived
1
0
Fork 0
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

179 lines
6.1 KiB
C

3 years ago
#include <stdio.h>
#include <stdlib.h>
/* Ребра */
3 years ago
typedef struct edge {
int begin;
int end;
int len;
} Edge;
int count_edge(int **adj, int n);
Edge* create_edge_vector(int **adj, int n, int size);
void print_edges(int** adj, int n);
int** solve(Edge* vector, int size, int size_vertex);
int vector_compare(const void *a, const void *b);
void paint_vertices(Edge* vector, int size, int need_vertix, int saved_color, int *paint);
int main() {
/* n - количество вершин, size - количество ребер */
int n;
scanf("%d", &n);
int **adj = (int**)calloc(n, sizeof(int*));
for (int i = 0; i < n; i++) {
adj[i] = (int*)calloc(n, sizeof(int));
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &adj[i][j]);
}
}
/* Подсчет количества ребер в исходной матрице смежности */
int size = count_edge(adj, n);
/* Создаем массив с ребрами */
3 years ago
Edge *vector = create_edge_vector(adj, n, size);
/* Сортируем ребра по длине, сначала самые короткие */
qsort(vector, size, sizeof(Edge), vector_compare);
int **res = solve(vector, size, n);
/* Вывод списка имеющихся ребер по матрице смежности */
3 years ago
print_edges(res, n);
/* Освобождаем память */
for (int i = 0; i < n; i++) {
free(adj[i]);
}
free(adj);
for (int i = 0; i < n; i++) {
free(res[i]);
}
free(res);
free(vector);
}
int **solve(Edge* vector, int size, int v) {
/* size - ребра, v - вершины */
3 years ago
/* Результирующее остовное дерево в виде матрицы смежности */
int** res = (int**)calloc(v, sizeof(int*));
for (int i = 0; i < v; i++) {
res[i] = (int*)calloc(v, sizeof(int));
}
/* Массив с окраской каждой вершины */
int *paint = (int*)calloc(v, sizeof(int));
3 years ago
/* Количество рассмотренных вершин */
int n = 0;
/* Текущий цвет */
3 years ago
int color = 1;
/* Сохраненный цвет для перекрашивания (объединение двух компонент) */
3 years ago
int saved_color;
/* Пока не раскрашены все вершины */
while (n != size ) {
/* Проверяем, соединяет ли очередное ребро вершины из уже имеющейся компоненты одного цвета (цвет 0 - отсутствие цвета) */
3 years ago
if ((paint[vector[n].begin] == paint[vector[n].end]) && (paint[vector[n].begin] != 0 || paint[vector[n].end] != 0)) {
n++;
continue;
}
else {
/* Создание новой компоненты связности и добавление результата в результирующую матрицу смежности */
/* Обе вершины бесцветные */
if (paint[vector[n].begin] == 0 && paint[vector[n].end] == 0) {
3 years ago
paint[vector[n].begin] = color;
paint[vector[n].end] = color;
3 years ago
res[vector[n].begin][vector[n].end] = vector[n].len;
/* Создаем новый цвет */
color++;
}
/* Присоединение неокрашенной вершины к существующей компоненте связности */
else if (paint[vector[n].begin] == 0) {
paint[vector[n].begin] = paint[vector[n].end];
3 years ago
res[vector[n].begin][vector[n].end] = vector[n].len;
}
else if (paint[vector[n].end] == 0) {
paint[vector[n].end] = paint[vector[n].begin];
3 years ago
res[vector[n].begin][vector[n].end] = vector[n].len;
}
/* Объединение компонент связности */
else {
/* Сохраняем цвет той компоненты, которую будем перекрашивать */
saved_color = paint[vector[n].end];
paint[vector[n].end] = paint[vector[n].begin];
3 years ago
res[vector[n].begin][vector[n].end] = vector[n].len;
3 years ago
/* Перекрашиваем вторую компоненту в цвет первой */
paint_vertices(vector, size, vector[n].end, saved_color, paint);
}
n++;
}
}
free(paint);
return res;
}
void print_edges(int **adj, int n) {
3 years ago
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (adj[i][j] != 0) {
printf("%d-%d: %d\n", i, j, adj[i][j]);
3 years ago
}
}
}
}
Edge* create_edge_vector(int **adj, int n, int size) {
Edge* vector = (Edge*)calloc(size, sizeof(Edge));
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (adj[i][j] != 0) {
/* Заполняем с конца */
size--;
vector[size].begin = i;
vector[size].end = j;
vector[size].len = adj[i][j];
}
}
}
return vector;
}
int count_edge(int **adj, int n) {
int res = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (adj[i][j] != 0) {
res++;
}
}
}
return res;
}
int vector_compare(const void *a, const void *b) {
return ((const Edge *)a)->len - ((const Edge *)b)->len;
}
void paint_vertices(Edge* vector, int size, int need_vertix, int saved_color, int *paint) {
for (int i = 0; i < size; i++) {
/* Если текущее ребро выходит из нужной вершины */
3 years ago
if (vector[i].begin == need_vertix) {
/* Если другой конец ребра - нужный по цвету (старый), то красим в цвет исходной вершины */
if (paint[vector[i].end] == saved_color) {
paint[vector[i].end] = paint[need_vertix];
/* Рекурсивно вызываем покраску для конца ребра */
paint_vertices(vector, size, vector[i].end, saved_color, paint);
}
}
/* Если текущее ребро заканчивается в нужной вершине */
else if (vector[i].end == need_vertix) {
/* Аналогично случаю выше, но вызываем для начала ребра */
if (paint[vector[i].begin] == saved_color) {
paint[vector[i].begin] = paint[need_vertix];
paint_vertices(vector, size, vector[i].begin, saved_color, paint);
}
}
}
}