|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <limits.h>
|
|
|
|
|
|
|
|
|
|
/* O(n^2) */
|
|
|
|
|
|
|
|
|
|
int* solve(int** massiv, int n, int x); // 0 вершина(можно заменить в коде)
|
|
|
|
|
void route(int** massiv, int* problem, int n, int x);// для 0 вершины
|
|
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
|
int n;
|
|
|
|
|
int x;
|
|
|
|
|
|
|
|
|
|
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]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Номер вершины */
|
|
|
|
|
scanf("%d", &x);
|
|
|
|
|
|
|
|
|
|
int *res = solve(adj, n, x);
|
|
|
|
|
|
|
|
|
|
route(adj, res, n, x);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
|
|
|
free(adj[i]);
|
|
|
|
|
}
|
|
|
|
|
free(adj);
|
|
|
|
|
|
|
|
|
|
free(res);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int *solve(int **adj, int n, int x) {
|
|
|
|
|
/* Пройденные вершины - 1, непройденные - 0 */
|
|
|
|
|
int *vertics = (int*)calloc(n, sizeof(int));
|
|
|
|
|
/* Вершины, из которых быстрее всего добраться */
|
|
|
|
|
int *res = (int*)calloc(n, sizeof(int));
|
|
|
|
|
/* Количество пройденных вершин */
|
|
|
|
|
int size = 1;
|
|
|
|
|
/* Массив с длинами ребер, из которых выбираем */
|
|
|
|
|
int* arr = (int*)calloc(n, sizeof(int));
|
|
|
|
|
/* Начальная вершина */
|
|
|
|
|
int vertic = x;
|
|
|
|
|
/* Делаем начальную вершину выбранной */
|
|
|
|
|
vertics[vertic] = 1;
|
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
|
|
|
arr[i] = adj[vertic][i];
|
|
|
|
|
res[i] = vertic;
|
|
|
|
|
}
|
|
|
|
|
while (size != n) {
|
|
|
|
|
int min = INT_MAX;
|
|
|
|
|
int k;
|
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
|
|
|
/* Пропускаем пройденные вершины */
|
|
|
|
|
if (vertics[i] == 1) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
/* Ищем вершину, до которой ближе всего (с номером k) */
|
|
|
|
|
if (min > arr[i]) {
|
|
|
|
|
min = arr[i];
|
|
|
|
|
k = i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Отмечаем найденную вершину "пройденной" */
|
|
|
|
|
vertics[k] = 1;
|
|
|
|
|
/* Смотрим, изменится ли наш массив рёбер, если будем "шагать" из выбранной вершины */
|
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
|
|
|
/* Игнорируем пройденные вершины */
|
|
|
|
|
if (vertics[i] == 1) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
/* Если из вершины k ближе до вершины i, то обновляем знaчение для i */
|
|
|
|
|
if (arr[i] > min + adj[k][i]) {
|
|
|
|
|
arr[i] = min + adj[k][i];
|
|
|
|
|
res[i] = k;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size++;
|
|
|
|
|
}
|
|
|
|
|
free(vertics);
|
|
|
|
|
free(arr);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void route(int **adj, int *res, int n, int x) {
|
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
|
|
|
/* Игнорируем петли */
|
|
|
|
|
if (i == x) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
int w = i;
|
|
|
|
|
/* Суммарная длина */
|
|
|
|
|
int sum = 0;
|
|
|
|
|
/* Если есть прямой короткий путь, то выводим его */
|
|
|
|
|
if (res[i] == x) {
|
|
|
|
|
sum = adj[x][i];
|
|
|
|
|
printf("%d: %d-%d\n", i, i, x);
|
|
|
|
|
}
|
|
|
|
|
/* Иначе, последовательно идем по вершинам из res */
|
|
|
|
|
else {
|
|
|
|
|
printf("%d: %d-", i, i);
|
|
|
|
|
while (res[w] != x) {
|
|
|
|
|
sum += adj[res[w]][w];
|
|
|
|
|
printf("%d-", res[w]);
|
|
|
|
|
w = res[w];
|
|
|
|
|
}
|
|
|
|
|
sum += adj[x][w];
|
|
|
|
|
printf("%d\n", x);
|
|
|
|
|
}
|
|
|
|
|
printf("Расстояние: %d\n###\n", sum);
|
|
|
|
|
}
|
|
|
|
|
}
|