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.

147 lines
4.1 KiB
C

3 years ago
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
/* O(n^2) */
typedef struct vertex_s {
int val;
/* 0 - непройденная, 1 - пройденная */
int sel;
} vertex;
3 years ago
vertex *solve(unsigned int **adj, int n, int x);
void route(unsigned int **adj, vertex *res, int n, int x);
3 years ago
int main() {
/* Количество вершин и номер нужной для отсчета вершины */
3 years ago
int n;
int x;
scanf("%d", &n);
unsigned int **adj = (unsigned int**)calloc(n, sizeof(unsigned int *));
3 years ago
for (int i = 0; i < n; i++) {
adj[i] = (unsigned int*)calloc(n, sizeof(unsigned int));
3 years ago
}
/* В нашей матрице смежности 0 обозначает отсутствие пути из одной вершины в другую */
3 years ago
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &adj[i][j]);
if (!adj[i][j])
adj[i][j] = INT_MAX;
3 years ago
}
}
#ifdef _DEBUG
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
printf("%d\t", adj[i][j]);
}
printf("\n");
}
#endif
3 years ago
scanf("%d", &x);
vertex *res = solve(adj, n, x);
3 years ago
/* Вывод результата, расстояние от каждой вершины до данной с путем */
3 years ago
route(adj, res, n, x);
/* Освобождаем память */
3 years ago
for (int i = 0; i < n; i++) {
free(adj[i]);
}
free(adj);
free(res);
}
vertex *solve(unsigned int **adj, int n, int x) {
vertex *res = (vertex *)calloc(n, sizeof(vertex));
3 years ago
/* Количество пройденных вершин */
int size = 1;
/* Массив с длинами ребер, из которых выбираем для каждой вершины */
unsigned int *distance = (unsigned int*)calloc(n, sizeof(unsigned int));
3 years ago
/* Начальная вершина */
int v = x;
3 years ago
/* Делаем начальную вершину выбранной */
res[v].sel = 1;
/* Смотрим, как выбранная вершина соотносится с другими, заполняем массив расстояний */
3 years ago
for (int i = 0; i < n; i++) {
distance[i] = adj[v][i];
res[i].val = v;
3 years ago
}
/* Пока не переберем все вершины */
3 years ago
while (size != n) {
/* Минимальное расстояние до вершины, изначально - бесконечность */
unsigned int min = INT_MAX;
/* Номер очередной вершины */
3 years ago
int k;
for (int i = 0; i < n; i++) {
/* Пропускаем пройденные вершины */
if (res[i].sel == 1) {
3 years ago
continue;
}
/* Ищем вершину, до которой ближе всего (с номером k) */
if (min >= distance[i]) {
min = distance[i];
3 years ago
k = i;
}
}
/* Отмечаем найденную вершину "пройденной" */
res[k].sel = 1;
3 years ago
/* Смотрим, изменится ли наш массив рёбер, если будем "шагать" из выбранной вершины */
for (int i = 0; i < n; i++) {
/* Игнорируем пройденные вершины */
if (res[i].sel == 1) {
3 years ago
continue;
}
/* Если из вершины k ближе до вершины i, то обновляем знaчение для i */
if (distance[i] > min + adj[k][i]) {
distance[i] = min + adj[k][i];
res[i].val = k;
3 years ago
}
}
size++;
}
free(distance);
3 years ago
return res;
}
3 years ago
void route(unsigned int **adj, vertex *res, int n, int x) {
3 years ago
for (int i = 0; i < n; i++) {
/* Игнорируем петли */
if (i == x) {
continue;
}
int w = i;
/* Суммарная длина */
int sum = 0;
/* Если есть прямой короткий путь, то выводим его */
if (res[i].val == x) {
3 years ago
sum = adj[x][i];
printf("%d: %d-%d\n", i, i, x);
}
/* Иначе, последовательно идем по вершинам из res */
else {
printf("%d: %d-", i, i);
while (res[w].val != x) {
sum += adj[res[w].val][w];
printf("%d-", res[w].val);
w = res[w].val;
3 years ago
}
sum += adj[x][w];
printf("%d\n", x);
}
printf("Расстояние: %d\n###\n", sum);
}
}