Computer >> Máy Tính >  >> Lập trình >> Lập trình

Thuật toán Ford Fulkerson


Thuật toán Ford-Fulkerson được sử dụng để phát hiện luồng cực đại từ đỉnh bắt đầu đến đỉnh chìm trong một đồ thị nhất định. Trong đồ thị này, mọi cạnh đều có công suất. Hai đỉnh được cung cấp có tên Nguồn và Chìm. Đỉnh nguồn có tất cả cạnh ra ngoài, không có cạnh trong và phần chìm sẽ có tất cả cạnh vào trong không có cạnh ra ngoài.

Thuật toán Ford Fulkerson

Có một số ràng buộc:

  • Dòng chảy trên một cạnh không vượt quá khả năng nhất định của biểu đồ đó.
  • Luồng đến và luồng đi cũng sẽ bằng nhau đối với mọi cạnh, ngoại trừ nguồn và bồn rửa.

Đầu vào và Đầu ra

Input:
The adjacency matrix:
0 10 0 10 0  0
0  0 4  2 8  0
0  0 0  0 0 10
0  0 0  0 9  0
0  0 6  0 0 10
0  0 0  0 0  0

Output:
Maximum flow is: 19

Thuật toán

bfs (vert, bắt đầu, chìm)

Đầu vào: Danh sách đỉnh, nút bắt đầu và nút chìm.

Đầu ra - Đúng khi bồn rửa được truy cập.

Begin
   initially mark all nodes as unvisited
   state of start as visited
   predecessor of start node is φ
   insert start into the queue qu
   while qu is not empty, do
      delete element from queue and set to vertex u
      for all vertices i, in the residual graph, do
         if u and i are connected, and i is unvisited, then
            add vertex i into the queue
            predecessor of i is u
            mark i as visited
      done
   done
   return true if state of sink vertex is visited
End

fordFulkerson (vert, nguồn, chìm)

Đầu vào: Danh sách đỉnh, đỉnh nguồn và đỉnh chìm.

Đầu ra - Lưu lượng tối đa từ đầu đến chìm.

Begin
   create a residual graph and copy given graph into it
   while bfs(vert, source, sink) is true, do
      pathFlow := ∞
      v := sink vertex
      while v ≠ start vertex, do
         u := predecessor of v
         pathFlow := minimum of pathFlow and residualGraph[u, v]
         v := predecessor of v
      done

      v := sink vertex
      while v ≠ start vertex, do
         u := predecessor of v
         residualGraph[u,v] := residualGraph[u,v] – pathFlow
         residualGraph[v,u] := residualGraph[v,u] – pathFlow
         v := predecessor of v
      done

      maFlow := maxFlow + pathFlow
   done
   return maxFlow
End

Ví dụ

#include<iostream>
#include<queue>
#define NODE 6
using namespace std;

typedef struct node {
   int val;
   int state; //status
   int pred; //predecessor
}node;

int minimum(int a, int b) {
   return (a<b)?a:b;
}

int resGraph[NODE][NODE];

/* int graph[NODE][NODE] = {
   {0, 16, 13, 0, 0, 0},
   {0, 0, 10, 12, 0, 0},
   {0, 4, 0, 0, 14, 0},
   {0, 0, 9, 0, 0, 20},
   {0, 0, 0, 7, 0, 4},
   {0, 0, 0, 0, 0, 0}
}; */

int graph[NODE][NODE] = {
   {0, 10, 0, 10, 0, 0},
   {0, 0, 4, 2, 8, 0},
   {0, 0, 0, 0, 0, 10},
   {0, 0, 0, 0, 9, 0},
   {0, 0, 6, 0, 0, 10},
   {0, 0, 0, 0, 0, 0}
};
                   
int bfs(node *vert, node start, node sink) {
   node u;
   int i, j;
   queue<node> que;

   for(i = 0; i<NODE; i++) {
      vert[i].state = 0;    //not visited
   }

   vert[start.val].state = 1;   //visited
   vert[start.val].pred = -1;   //no parent node
   que.push(start);   //insert starting node

   while(!que.empty()) {
      //delete from queue and print
      u = que.front();
      que.pop();

      for(i = 0; i<NODE; i++) {
         if(resGraph[u.val][i] > 0 && vert[i].state == 0) {
            que.push(vert[i]);
            vert[i].pred = u.val;
            vert[i].state = 1;
         }
      }
   }
   return (vert[sink.val].state == 1);
}

int fordFulkerson(node *vert, node source, node sink) {
   int maxFlow = 0;
   int u, v;

   for(int i = 0; i<NODE; i++) {
      for(int j = 0; j<NODE; j++) {
         resGraph[i][j] = graph[i][j];    //initially residual graph is main graph
      }
   }

   while(bfs(vert, source, sink)) {    //find augmented path using bfs algorithm
      int pathFlow = 999;//as infinity
      for(v = sink.val; v != source.val; v=vert[v].pred) {
         u = vert[v].pred;
         pathFlow = minimum(pathFlow, resGraph[u][v]);
      }

      for(v = sink.val; v != source.val; v=vert[v].pred) {
         u = vert[v].pred;
         resGraph[u][v] -= pathFlow;   //update residual capacity of edges
         resGraph[v][u] += pathFlow;   //update residual capacity of reverse edges
      }

      maxFlow += pathFlow;
   }
   return maxFlow;    //the overall max flow
}

int main() {
   node vertices[NODE];
   node source, sink;

   for(int i = 0; i<NODE; i++) {
      vertices[i].val = i;
   }

   source.val = 0;
   sink.val = 5;
   int maxFlow = fordFulkerson(vertices, source, sink);
   cout << "Maximum flow is: " << maxFlow << endl;
}

Đầu ra

Maximum flow is: 19