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.

168 lines
5.4 KiB
C

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <stdio.h>
#include <stdlib.h>
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);
Edge *vector = create_edge_vector(adj, n, size);
/* Сортируем ребра по длине, сначала самые короткие */
qsort(vector, size, sizeof(Edge), vector_compare);
int **res = solve(vector, size, n);
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) {
/* Результирующее остовное дерево в виде матрицы смежности */
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));
/* Количество рассмотренных вершин */
int n = 0;
int color = 1;
int saved_color;
/* Пока не раскрашены все вершины */
while (n != size ) {
/* Проверяем на цикл */
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) {//обе вершины незакрашены
paint[vector[n].begin] = color;
paint[vector[n].end] = color;
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];
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];
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];
res[vector[n].begin][vector[n].end] = vector[n].len;
/* Перекрашиваем вторую компоненту в цвет первой */
paint_vertices(vector, size, vector[n].end, saved_color, paint);
}
n++;
}
}
free(paint);
return res;
}
void print_edges(int** massiv, int n) {
printf("Решение:\n");
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (massiv[i][j] != 0) {
printf("%d-%d: %d\n", i, j, massiv[i][j]);
}
}
}
}
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++) {
/* Если текущая ребро выходит из нужной вершины */
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);
}
}
}
}