| 
619 | 619 | 
 
  | 
620 | 620 |   this.algCoffee.edmondsKarp = edmondsKarp;  | 
621 | 621 | 
 
  | 
 | 622 | +}).call(this);  | 
 | 623 | +;(function() {  | 
 | 624 | +  var AdjacencyList, fordFulkerson;  | 
 | 625 | + | 
 | 626 | +  if (typeof module !== 'undefined') {  | 
 | 627 | +    AdjacencyList = require('./../data-structures/adjacency-list').algCoffee.AdjacencyList;  | 
 | 628 | +  } else {  | 
 | 629 | +    AdjacencyList = algCoffee.AdjacencyList;  | 
 | 630 | +  }  | 
 | 631 | + | 
 | 632 | +  fordFulkerson = function(graph, sourceVertex, sinkVertex) {  | 
 | 633 | +    var aux, createResidualGraph, eliminateAntiParallelEdges, findAugmentingPath, maximumFlow, residualGraph;  | 
 | 634 | +    sourceVertex += '';  | 
 | 635 | +    sinkVertex += '';  | 
 | 636 | +    createResidualGraph = function() {  | 
 | 637 | +      var residualGraph, source, target, value, weight, _ref;  | 
 | 638 | +      residualGraph = new AdjacencyList();  | 
 | 639 | +      _ref = graph.edges;  | 
 | 640 | +      for (source in _ref) {  | 
 | 641 | +        value = _ref[source];  | 
 | 642 | +        for (target in value) {  | 
 | 643 | +          weight = value[target];  | 
 | 644 | +          if (graph.getEdgeWeight(target, source) === void 0) {  | 
 | 645 | +            residualGraph.addEdge(target, source, 0);  | 
 | 646 | +          }  | 
 | 647 | +          residualGraph.addEdge(source, target, weight);  | 
 | 648 | +        }  | 
 | 649 | +      }  | 
 | 650 | +      return residualGraph;  | 
 | 651 | +    };  | 
 | 652 | +    eliminateAntiParallelEdges = function() {  | 
 | 653 | +      var newVertex, source, target, value, weight, _ref, _results;  | 
 | 654 | +      _ref = residualGraph.edges;  | 
 | 655 | +      _results = [];  | 
 | 656 | +      for (source in _ref) {  | 
 | 657 | +        value = _ref[source];  | 
 | 658 | +        _results.push((function() {  | 
 | 659 | +          var _results1;  | 
 | 660 | +          _results1 = [];  | 
 | 661 | +          for (target in value) {  | 
 | 662 | +            weight = value[target];  | 
 | 663 | +            if (residualGraph.edges[target][source] !== void 0) {  | 
 | 664 | +              newVertex = parseInt(Math.random() * residualGraph.amountOfVertices * 10);  | 
 | 665 | +              while (residualGraph.edges[newVertex] !== void 0) {  | 
 | 666 | +                newVertex = parseInt(Math.random() * residualGraph.amountOfVertices * 10);  | 
 | 667 | +              }  | 
 | 668 | +              residualGraph.addEdge(source, newVertex, weight);  | 
 | 669 | +              residualGraph.addEdge(newVertex, target, weight);  | 
 | 670 | +              _results1.push(residualGraph.deleteEdge(source, target));  | 
 | 671 | +            } else {  | 
 | 672 | +              _results1.push(void 0);  | 
 | 673 | +            }  | 
 | 674 | +          }  | 
 | 675 | +          return _results1;  | 
 | 676 | +        })());  | 
 | 677 | +      }  | 
 | 678 | +      return _results;  | 
 | 679 | +    };  | 
 | 680 | +    findAugmentingPath = function(sourceVertex, sinkVertex) {  | 
 | 681 | +      var currentVertex, currentVertexRoommates, maximumFlowThroughPath, parent, parents, queue, target, v, visitedVertices, weight;  | 
 | 682 | +      parents = {};  | 
 | 683 | +      maximumFlowThroughPath = {};  | 
 | 684 | +      visitedVertices = {};  | 
 | 685 | +      queue = [];  | 
 | 686 | +      visitedVertices[sourceVertex] = true;  | 
 | 687 | +      queue.push(sourceVertex);  | 
 | 688 | +      while (queue.length > 0) {  | 
 | 689 | +        currentVertex = queue.shift();  | 
 | 690 | +        if (currentVertex === sinkVertex) {  | 
 | 691 | +          v = sinkVertex;  | 
 | 692 | +          parent = parents[v];  | 
 | 693 | +          while (parent !== void 0) {  | 
 | 694 | +            residualGraph.edges[parent][v] -= maximumFlowThroughPath[sinkVertex];  | 
 | 695 | +            residualGraph.edges[v][parent] += maximumFlowThroughPath[sinkVertex];  | 
 | 696 | +            if (residualGraph.edges[parent][v] === 0) {  | 
 | 697 | +              residualGraph.deleteEdge(parent, v);  | 
 | 698 | +            }  | 
 | 699 | +            v = parent;  | 
 | 700 | +            parent = parents[parent];  | 
 | 701 | +          }  | 
 | 702 | +          return maximumFlowThroughPath[sinkVertex];  | 
 | 703 | +        }  | 
 | 704 | +        currentVertexRoommates = residualGraph.getRoommates(currentVertex);  | 
 | 705 | +        for (target in currentVertexRoommates) {  | 
 | 706 | +          weight = currentVertexRoommates[target];  | 
 | 707 | +          if (visitedVertices[target] === void 0) {  | 
 | 708 | +            parents[target] = currentVertex;  | 
 | 709 | +            if (maximumFlowThroughPath[currentVertex] === void 0) {  | 
 | 710 | +              maximumFlowThroughPath[target] = weight;  | 
 | 711 | +            } else {  | 
 | 712 | +              maximumFlowThroughPath[target] = Math.min(maximumFlowThroughPath[currentVertex], weight);  | 
 | 713 | +            }  | 
 | 714 | +            visitedVertices[target] = true;  | 
 | 715 | +            queue.push(target);  | 
 | 716 | +          }  | 
 | 717 | +        }  | 
 | 718 | +      }  | 
 | 719 | +      return void 0;  | 
 | 720 | +    };  | 
 | 721 | +    residualGraph = createResidualGraph();  | 
 | 722 | +    eliminateAntiParallelEdges();  | 
 | 723 | +    maximumFlow = 0;  | 
 | 724 | +    aux = 0;  | 
 | 725 | +    while ((aux = findAugmentingPath(sourceVertex, sinkVertex)) !== void 0) {  | 
 | 726 | +      maximumFlow += aux;  | 
 | 727 | +    }  | 
 | 728 | +    return maximumFlow;  | 
 | 729 | +  };  | 
 | 730 | + | 
 | 731 | +  this.algCoffee = this.algCoffee ? this.algCoffee : {};  | 
 | 732 | + | 
 | 733 | +  this.algCoffee.fordFulkerson = fordFulkerson;  | 
 | 734 | + | 
622 | 735 | }).call(this);  | 
623 | 736 | ;(function() {  | 
624 | 737 |   var AdjacencyList, depthFirstSearch, kosaraju;  | 
 | 
0 commit comments