@ -4,31 +4,51 @@
/* O(n^2) */
int * solve ( int * * massiv , int n , int x ) ; // 0 вершина(можно заменить в коде)
void route ( int * * massiv , int * problem , int n , int x ) ; // для 0 вершины
typedef struct vertex_s {
int val ;
/* 0 - непройденная, 1 - пройденная */
int sel ;
} vertex ;
vertex * solve ( unsigned int * * adj , int n , int x ) ; // 0 вершина(можно заменить в коде)
void route ( int * * adj , vertex * res , int n , int x ) ; // для 0 вершины
int main ( ) {
/* Количество вершин и номер нужной для отсчета вершины */
int n ;
int x ;
scanf ( " %d " , & n ) ;
int * * adj = ( int* * ) calloc ( n , sizeof ( int* ) ) ;
unsigned int * * adj = ( unsigned int* * ) calloc ( n , sizeof ( unsigned int * ) ) ;
for ( int i = 0 ; i < n ; i + + ) {
adj [ i ] = ( int* ) calloc ( n , sizeof ( int ) ) ;
adj [ i ] = ( unsigned int* ) calloc ( n , sizeof ( unsigned int ) ) ;
}
/* В нашей матрице смежности 0 обозначает отсутствие пути из одной вершины в другую */
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 ;
}
}
/* Номер вершины */
# 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
scanf ( " %d " , & x ) ;
int * res = solve ( adj , n , x ) ;
vertex * res = solve ( adj , n , x ) ;
/* Вывод результата, расстояние от каждой вершины до данной с путем */
route ( adj , res , n , x ) ;
/* Освобождаем память */
for ( int i = 0 ; i < n ; i + + ) {
free ( adj [ i ] ) ;
}
@ -37,60 +57,67 @@ int main() {
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 ) ) ;
vertex * solve ( unsigned int * * adj , int n , int x ) {
vertex * res = ( vertex * ) calloc ( n , sizeof ( vertex ) ) ;
/* Количество пройденных вершин */
int size = 1 ;
/* Массив с длинами р е б е р , из которых выбираем */
int * arr = ( int * ) calloc ( n , sizeof ( int ) ) ;
/* Массив с длинами р е б е р , из которых выбираем для каждой вершины */
unsigned int * distance = ( unsigned int * ) calloc ( n , sizeof ( unsigned int ) ) ;
/* Начальная вершина */
int vertic = x ;
int v = x ;
/* Делаем начальную вершину выбранной */
vertics [ vertic ] = 1 ;
res [ v ] . sel = 1 ;
/* Смотрим, как выбранная вершина соотносится с другими, заполняем массив расстояний */
for ( int i = 0 ; i < n ; i + + ) {
arr [ i ] = adj [ vertic ] [ i ] ;
res [ i ] = v ertic ;
distance [ i ] = adj [ v ] [ i ] ;
res [ i ] . val = v ;
}
/* Пока не переберем все вершины */
while ( size ! = n ) {
int min = INT_MAX ;
/* Минимальное расстояние до вершины, изначально - бесконечность */
unsigned int min = INT_MAX ;
/* Номер очередной вершины */
int k ;
for ( int i = 0 ; i < n ; i + + ) {
/* Пропускаем пройденные вершины */
if ( vertics[ i ] = = 1 ) {
if ( res[ i ] . sel = = 1 ) {
continue ;
}
/* Ищем вершину, до которой ближе всего (с номером k) */
if ( min > arr [ i ] ) {
min = arr [ i ] ;
if ( min > = distance [ i ] ) {
min = distance [ i ] ;
k = i ;
}
}
/* Отмечаем найденную вершину "пройденной" */
vertics[ k ] = 1 ;
res[ k ] . sel = 1 ;
/* Смотрим, изменится ли наш массив рёбер, если будем "шагать" из выбранной вершины */
for ( int i = 0 ; i < n ; i + + ) {
/* Игнорируем пройденные вершины */
if ( vertics[ i ] = = 1 ) {
if ( res[ i ] . sel = = 1 ) {
continue ;
}
/* Если из вершины k ближе до вершины i, то обновляем знaче ние для i */
if ( arr [ i ] > min + adj [ k ] [ i ] ) {
arr [ i ] = min + adj [ k ] [ i ] ;
res [ i ] = k ;
if ( distance [ i ] > min + adj [ k ] [ i ] ) {
distance [ i ] = min + adj [ k ] [ i ] ;
res [ i ] . val = k ;
}
}
size + + ;
}
free ( vertics ) ;
free ( arr ) ;
free ( distance ) ;
return res ;
}
void route ( int * * adj , int * res , int n , int x ) {
void route ( int * * adj , vertex * res , int n , int x ) {
for ( int i = 0 ; i < n ; i + + ) {
/* Игнорируем петли */
if ( i = = x ) {
@ -100,17 +127,17 @@ void route(int **adj, int *res, int n, int x) {
/* Суммарная длина */
int sum = 0 ;
/* Если есть прямой короткий путь, то выводим е г о */
if ( res [ i ] = = x ) {
if ( res [ i ] . val = = 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 ] ;
while ( res [ w ] . val ! = x ) {
sum + = adj [ res [ w ] .val ][ w ] ;
printf ( " %d- " , res [ w ] .val );
w = res [ w ] .val ;
}
sum + = adj [ x ] [ w ] ;
printf ( " %d \n " , x ) ;