Advertisement
dmkozyrev

max_flow

Jan 22nd, 2016
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.14 KB | None | 0 0
  1. #include <stdio.h>
  2.  
  3. // Чтение графа происходит из файла in.txt, который устроен следующим образом
  4. // Сначала идут три целых числа: n - количество вершин, a - пункт отправления, b - пункт назначения
  5. // Затем идет n строк по n целых чисел в каждой строке - матрица смежности графа
  6. // Запись осуществляется в файл out.txt
  7. // В первой строчке записывается величина максимального потока
  8. // Затем записывается матрица смежности нашего потока
  9.  
  10. unsigned const int MAX_SIZE = 100;
  11.  
  12. void read_graph(int * graph, int * n, int * a, int * b, const char * filename);
  13. int search_path(int * graph, int n, int a, int b, int * path, int * path_len);
  14. int search_flow(int * graph, int n, int a, int b, int * flow);
  15. int search_min(int * graph, int n, int * path, int path_len);
  16. void update_flow(int * graph, int * flow, int n, int d, int * path, int path_len);
  17. void write_flow(int * flow, int n, int max_flow, const char * filename);
  18. void print_path(int * path, int n);
  19.  
  20. int pop(int * queue, int * n);
  21. void push(int * queue, int * n, int value);
  22.  
  23. int main(){
  24.     int graph[MAX_SIZE][MAX_SIZE], flow[MAX_SIZE][MAX_SIZE]; // Матрица смежности графа и поток
  25.     int n, a, b, max_flow; // n - количество вершин. Из вершины a в вершину b ищем минимальный путь. max_flow - величина максимального потока
  26.    
  27.     int * ptr_graph = (int*)graph; // Указатель на матрицу смежности
  28.     int * ptr_flow = (int*)flow; // Указатель на поток
  29.    
  30.     read_graph(ptr_graph, &n, &a, &b, "in.txt"); // Считываем граф
  31.    
  32.     if (max_flow = search_flow(ptr_graph, n, a, b, ptr_flow)) // Ищем максимальный поток
  33.         printf("The max flow has been successfully found!\n");
  34.     else
  35.         printf("The max flow does not exist!\n");
  36.    
  37. //  Записываем максимальный поток и его величину в файл:
  38.     write_flow(ptr_flow, n, max_flow, "out.txt");
  39.    
  40.     return 0;
  41. }
  42.  
  43. void print_path(int * path, int n){
  44. //  Вывод пути на экран
  45.     int i;
  46.     for (i = 0; i < n; i++)
  47.         printf("%d ", path[i]);
  48.     printf("\n");
  49. }
  50.  
  51. int search_flow(int * graph, int n, int a, int b, int * flow){
  52.     int path[MAX_SIZE], path_len = 0, d;
  53.    
  54. //  Пока мы можем найти какой - либо путь из вершины а в вершину b
  55.     while (search_path(graph, n, a, b, path, &path_len)) {
  56.         d = search_min(graph, n, path, path_len); // Вычисляем минимальную длину ребра на этом пути
  57.         update_flow(graph, flow, n, d, path, path_len); // Обновляем матрицу смежности и матрицу потока на величину d
  58.     }
  59.    
  60. //  Дальше суммируем длинны всех исходящих из вершины а ребер . Это и будет величина нашего максимального потока
  61.     int max_flow = 0, i;
  62.     for (i = 0; i < n; ++i)
  63.         if (d = *(flow+a*n+i))
  64.             max_flow += d;
  65.    
  66. //  Возвращаем найденную нами величину максимального потока
  67.     return max_flow;
  68. }
  69.  
  70. int search_min(int * graph, int n, int * path, int path_len){
  71. //  Данная функция ищет минимальную длину среди длин всех ребер маршрута path
  72.     int i = 0, d, min;
  73.     min = *(graph+path[i]*n+path[i+1]);
  74.     for (i = 1; i < path_len - 1; i++)
  75.         if (min > (d = *(graph+path[i]*n+path[i+1])))
  76.             min = d;
  77.     return min;    
  78. }
  79.  
  80. void update_flow(int * graph, int * flow, int n, int d, int * path, int path_len){
  81. //  Данная функция обновляет ребра маршрута path в матрице смежности graph и матрице потока flow на величину d
  82.     int i;
  83.     for (i = 0; i < path_len - 1; i++){
  84.         int a = path[i], b = path[i+1];
  85.         *(graph+a*n+b) -= d; // Вычитаем из длины ребра a -> b величину d
  86.         *(graph+b*n+a) += d; // Прибавлем ее к длине ребра b -> a
  87.         *(flow+a*n+b) += d; // Прибавляем ее к длине ребра a -> b в нашем потоке
  88.         *(flow+b*n+a) -= d; // Вычитаем ее из длины ребра b -> a в нашем потоке
  89.     }
  90. }
  91.  
  92. void read_graph(int * graph, int * n, int * a, int * b, const char * filename){
  93. //  Открываем файл для чтения:   
  94.     FILE *fp;
  95.     fp = fopen(filename, "r");
  96.    
  97. //  Считываем оттуда количество вершин, вершину a и вершину b:
  98.     fscanf(fp, "%d %d %d", n, a, b);
  99.    
  100. //  Считываем оттуда матрицу смежности графа:
  101.     int i, j;
  102.     for (i = 0; i < *n; i++)
  103.         for (j = 0; j < *n; j++)
  104.             fscanf(fp, "%d ", graph+(*n)*i+j);
  105.            
  106. //  Закрываем файл
  107.     fclose(fp);
  108. }
  109.  
  110. int pop(int * queue, int * n){
  111. //  Вынимаем элемент из очереди
  112.     int t = queue[0], i;
  113.     *n -= 1;
  114.     for(i = 0; i < *n; i++)
  115.         queue[i] = queue[i+1];
  116.     return t;
  117. }
  118.  
  119. void push(int * queue, int * n, int value){
  120. //  Кладем новый элемент в очередь
  121.     queue[*n] = value;
  122.     *n += 1;
  123. }
  124.  
  125. int search_path(int * graph, int n, int a, int b, int * path, int * path_len){
  126. //  Ищем минимальный путь поиском в ширину
  127.     *path_len = 0; // Длина пути
  128.    
  129.     int visited[MAX_SIZE], q[MAX_SIZE]; // Посещенные вершины и очередь для посещения вершин
  130.     int q_len = 0, i, j; // Длина очереди и счетчики циклов
  131.    
  132.     for(i = 0; i < n; i++) // Обнуляем массив посещенны вершин
  133.         visited[i] = -1;
  134.            
  135. //  Кидаем стартовую вершину в очередь и запоминаем, что мы ее посетили:
  136.     push(q, &q_len, a);
  137.     visited[a] = a;
  138.    
  139. //  Пока мы не обработали необходимые вершины, обрабатываем их:
  140.     while (q_len > 0) {
  141. //      Вынимаем очередную вершину:
  142.         const int t = pop(q, &q_len);
  143. //      Если мы достигли необходимой вершины, то логично бы прекратить поиск
  144.         if (t == b) break;
  145. //      В цикле кидаем в очередь все непосещенные смежные с вершиной t вершины:
  146.         for (i = 0; i < n; i++)
  147. //          ЕСЛИ существтует ребро t -> i и ЕСЛИ мы по нему еще не прошли:
  148.             if (*(graph+t*n+i) && visited[i] == -1 ) {
  149.                 visited[i] = t; // Сохраняем в visited[i] вершину t, из которой мы пришли в вершину i
  150.                 push(q, &q_len, i); // Кидаем вершину i в очередь обработки
  151.             }      
  152.     }
  153.    
  154. //  Возвращаемся из вершины b в вершину a по тому пути , который мы запомнили в visited
  155.     while ( b != a && visited[b] != -1 ){
  156.         push(path, path_len, b); // Кидаем вершины в вектор пути
  157.         b = visited[b];
  158.     }
  159.  
  160. //  Если нам удалось дойти до стартовой вершины , то кидаем ее в наш путь
  161.     if ( b == a ) push(path, path_len, a);
  162.    
  163. //  Приведение пути к нормальному виду (переворачиваем его)
  164.     for (i = 0, j = *path_len-1; i < j; ++i,--j){
  165.         int temp = path[i];
  166.         path[i] = path[j];
  167.         path[j] = temp;
  168.     }  
  169.    
  170.     return *path_len; // Возвращаем длину найденного пути
  171. }
  172.  
  173. void write_flow(int * flow, int n, int max_flow, const char * filename){
  174. //  Запись потока в файл
  175.     FILE *fp;
  176.     fp = fopen(filename, "w");
  177.     int i, j;
  178.     fprintf(fp, "%d\n", max_flow);
  179.     for (i = 0; i < n; i++, fprintf(fp, "\n"))
  180.         for(j = 0; j < n; j++)
  181.             fprintf(fp, "%d ", *(flow+i*n+j));
  182. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement