Advertisement
cd62131

dijkstra.c

May 14th, 2018
251
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.97 KB | None | 0 0
  1. #include <limits.h>
  2. #include <stdbool.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5.  
  6. #define NMAX 100
  7.  
  8. typedef struct visit visit;
  9. struct visit {
  10.     bool *visited;
  11.     int *distance, *prev;
  12.     int n;
  13. };
  14.  
  15. typedef struct weight weight;
  16. struct weight {
  17.     int *weight;
  18.     int n;
  19. };
  20.  
  21. static void clear_visit(visit *);
  22. static void clear_weight(weight *);
  23. static void controller(weight *);
  24. static void dijkstra(weight *, visit *);
  25. static inline int get_distance(visit *, int, int);
  26. static inline int get_prev(visit *, int, int);
  27. static inline bool get_visited(visit *, int, int);
  28. static inline int get_weight(weight *, int, int);
  29. static visit *init_visit(int);
  30. static weight *read_weight(void);
  31. static inline void set_distance(visit *, int, int, int);
  32. static inline void set_prev(visit *, int, int, int);
  33. static inline void set_visited(visit *, int, int, bool);
  34. static inline void set_weight(weight *, int, int, int);
  35. static void show_from_to(visit *, int, int);
  36. static void show_visit(visit *);
  37. static void show_weight(weight *);
  38.  
  39. static inline bool get_visited(visit *visit, int x, int y) {
  40.     return visit->visited[x * visit->n + y];
  41. }
  42.  
  43. static inline void set_visited(visit *visit, int x, int y, bool v) {
  44.     visit->visited[x * visit->n + y] = v;
  45. }
  46.  
  47. static inline int get_distance(visit *visit, int x, int y) {
  48.     return visit->distance[x * visit->n + y];
  49. }
  50.  
  51. static inline void set_distance(visit *visit, int x, int y, int v) {
  52.     visit->distance[x * visit->n + y] = v;
  53. }
  54.  
  55. static inline int get_prev(visit *visit, int x, int y) {
  56.     return visit->prev[x * visit->n + y];
  57. }
  58.  
  59. static inline void set_prev(visit *visit, int x, int y, int v) {
  60.     visit->prev[x * visit->n + y] = v;
  61. }
  62.  
  63. static inline int get_weight(weight *weight, int x, int y) {
  64.     return weight->weight[x * weight->n + y];
  65. }
  66.  
  67. static inline void set_weight(weight *weight, int x, int y, int v) {
  68.     weight->weight[x * weight->n + y] = v;
  69. }
  70.  
  71. static void show_weight(weight *weight) {
  72.     puts("data:");
  73.     for (int i = 1; i <= weight->n; i++) {
  74.         for (int j = 1; j <= weight->n; j++) {
  75.             if (get_weight(weight, i, j) < INT_MAX) {
  76.                 printf("%3d", get_weight(weight, i, j));
  77.             } else {
  78.                 printf("  x");
  79.             }
  80.         }
  81.         puts("");
  82.     }
  83.     puts("");
  84. }
  85.  
  86. static weight *read_weight(void) {
  87.     int n;
  88.     if (scanf("%d%*[^\n]", &n) != 1 || n > NMAX) {
  89.         return NULL;
  90.     }
  91.     weight *weight = calloc(sizeof(*weight), 1);
  92.     weight->n = n;
  93.     weight->weight = calloc(sizeof(*(weight->weight)), (n + 1) * (n + 1));
  94.     for (int i = 1; i <= n; i++) {
  95.         for (int j = 1; j <= n; j++) {
  96.             set_weight(weight, i, j, INT_MAX);
  97.         }
  98.     }
  99.     int x, y, v;
  100.     while (scanf("%d%d%d%*[^\n]", &x, &y, &v) == 3) {
  101.         set_weight(weight, x, y, v);
  102.         set_weight(weight, y, x, v);
  103.     }
  104.     show_weight(weight);
  105.     return weight;
  106. }
  107.  
  108. static visit *init_visit(int n) {
  109.     int nn = (n + 1) * (n + 1);
  110.     visit *visit = calloc(sizeof(*visit), 1);
  111.     visit->n = n;
  112.     visit->visited = calloc(sizeof(*(visit->visited)), nn);
  113.     visit->distance = calloc(sizeof(*(visit->distance)), nn);
  114.     visit->prev = calloc(sizeof(*(visit->prev)), nn);
  115.     for (int i = 1; i <= n; i++) {
  116.         for (int j = 1; j <= n; j++) {
  117.             set_visited(visit, i, j, false);
  118.             set_distance(visit, i, j, INT_MAX);
  119.         }
  120.     }
  121.     return visit;
  122. }
  123.  
  124. static void clear_visit(visit *visit) {
  125.     free(visit->visited);
  126.     free(visit->distance);
  127.     free(visit->prev);
  128.     free(visit);
  129. }
  130.  
  131. static void clear_weight(weight *weight) {
  132.     free(weight->weight);
  133.     free(weight);
  134. }
  135.  
  136. static void show_visit(visit *visit) {
  137.     for (int start = 1; start <= visit->n; start++) {
  138.         for (int i = 1; i <= visit->n; i++) {
  139.             int d = 0;
  140.             for (int j = i; j != start && get_visited(visit, start, j);
  141.                     j = get_prev(visit, start, j)) {
  142.                 d += get_distance(visit, start, j);
  143.                 printf("%d <- ", j);
  144.             }
  145.             printf("%d (%d)\n", start, d);
  146.         }
  147.         puts("");
  148.     }
  149. }
  150.  
  151. static void show_from_to(visit *visit, int from, int to) {
  152.     int d = 0;
  153.     for (int i = to; i != from && get_visited(visit, from, i);
  154.             i = get_prev(visit, from, i)) {
  155.         d += get_distance(visit, from, i);
  156.         printf("%d <- ", i);
  157.     }
  158.     printf("%d (%d)\n\n", from, d);
  159. }
  160.  
  161. static void controller(weight *weight) {
  162.     visit *visit = init_visit(weight->n);
  163.     dijkstra(weight, visit);
  164.     show_visit(visit);
  165.     for (int i = 1; i <= weight->n; i++) {
  166.         for (int j = i + 1; j <= weight->n; j++) {
  167.             show_from_to(visit, i, j);
  168.         }
  169.     }
  170.     clear_visit(visit);
  171. }
  172.  
  173. static void dijkstra(weight *weight, visit *visit) {
  174.     for (int start = 1, min; start <= weight->n; start++) {
  175.         int next = start;
  176.         set_distance(visit, start, next, 0);
  177.         do {
  178.             int i = next;
  179.             min = INT_MAX;
  180.             set_visited(visit, start, i, true);
  181.             for (int j = 1; j <= weight->n; j++) {
  182.                 if (get_visited(visit, start, j)) {
  183.                     continue;
  184.                 }
  185.                 if (get_weight(weight, i, j) < INT_MAX
  186.                         && get_distance(visit, start, i) + get_weight(weight, i, j)
  187.                         < get_distance(visit, start, j)) {
  188.                     set_distance(visit, start, j,
  189.                             get_distance(visit, start, i) + get_weight(weight, i, j));
  190.                     set_prev(visit, start, j, i);
  191.                 }
  192.                 if (get_distance(visit, start, j) < min) {
  193.                     min = get_distance(visit, start, j);
  194.                     next = j;
  195.                 }
  196.             }
  197.         } while (min < INT_MAX);
  198.     }
  199. }
  200.  
  201. int main(void) {
  202.     weight *weight = read_weight();
  203.     controller(weight);
  204.     clear_weight(weight);
  205.     return EXIT_SUCCESS;
  206. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement