Actividad de Evaluación Sumativa:
Modelado y Optimización de Redes de Flujo
Capı́tulo 10: Modelos de Redes
Asignatura: Estructuras Computacionales Discretas
Formulación de la Actividad
1. Introducción
El capı́tulo 10 del libro ”Matemáticas Discretas”de Johnsonbaugh introduce los con-
ceptos fundamentales de los modelos de redes, centrándose en el flujo máximo, el corte
mı́nimo y el acoplamiento (matching). Estos modelos no son meramente abstracciones
teóricas; constituyen la base de algoritmos que resuelven problemas crı́ticos en logı́stica,
telecomunicaciones, bioinformática, planificación de recursos y muchas otras áreas de la
ciencia y la ingenierı́a.
El objetivo de este trabajo es aplicar de manera rigurosa los conceptos y teoremas
del capı́tulo para modelar, analizar e implementar soluciones a un problema complejo del
mundo real, demostrando una comprensión profunda de la materia.
2. Objetivos de Aprendizaje
Al completar este proyecto, el estudiante deberá ser capaz de:
Modelar un sistema complejo como una red de flujo, identificando nodos, aristas,
capacidades, fuentes y sumideros.
Implementar el algoritmo de Ford-Fulkerson (o una de sus variantes como Edmonds-
Karp) para calcular el flujo máximo en una red.
Comprender y aplicar el Teorema de Flujo Máximo y Corte Mı́nimo para identificar
y analizar los cuellos de botella en un sistema.
Modelar un problema de asignación (matching) como un problema de flujo máximo.
Analizar los resultados obtenidos, interpretarlos en el contexto del problema y vin-
cularlos con literatura cientı́fica relevante.
1
3. Planteamiento del Problema
Se presenta un escenario multifacético de logı́stica humanitaria para la gestión de
desastres.
3.1. Escenario
Una organización de ayuda internacional debe gestionar la distribución de suministros
vitales (agua, alimentos, medicinas) tras un desastre natural que ha afectado a una región.
La infraestructura de transporte ha sido dañada, limitando la cantidad de carga que puede
moverse entre diferentes localidades.
Parte 1: Maximización del Flujo de Suministros. La organización tiene dos
depósitos de suministros principales (fuentes) y debe llevarlos a tres centros de
distribución en las zonas afectadas (sumideros). Existen varios puntos de tránsito
intermedios (ciudades, aeropuertos). Se le proporciona un mapa de la red logı́stica
con las capacidades de cada ruta (en toneladas/dı́a). Su primera tarea es determinar
la cantidad máxima total de suministros que pueden moverse desde los depósitos
hasta los centros de distribución diariamente.
Parte 2: Identificación de Cuellos de Botella. Tras calcular el flujo máximo,
la dirección de la organización necesita saber cuáles son las rutas más crı́ticas que
limitan el flujo total de ayuda. Si se pudieran invertir recursos para mejorar la
infraestructura, ¿en qué rutas especı́ficas se deberı́a enfocar para obtener el mayor
impacto en el aumento del flujo de ayuda? Debe identificar estas rutas y justificar
su elección basándose en la teorı́a.
Parte 3: Asignación Óptima de Voluntarios. Simultáneamente, un equipo de
voluntarios con diferentes especialidades (médicos, ingenieros, logistas) ha llegado.
Existen varias tareas crı́ticas que deben ser asignadas (atención médica, reparación
de infraestructuras, gestión de almacenes). Cada voluntario está calificado para
un subconjunto de estas tareas. Su tercera tarea es diseñar un plan para asignar
la mayor cantidad posible de voluntarios a tareas para las que están calificados,
asegurando que cada voluntario se asigne a una sola tarea y cada tarea sea realizada
por un solo voluntario.
4. Requisitos de Entrega
El estudiante deberá entregar un único documento en formato PDF que contenga:
1. Un informe técnico completo que incluya:
Una introducción y un marco teórico basado en el capı́tulo 10.
El modelado detallado de cada una de las tres partes del problema.
El código Python completo y comentado para la solución de cada parte.
Un análisis profundo de los resultados, interpretándolos en el contexto del
problema.
2
Una discusión que vincule los métodos utilizados con el estado del arte y la
literatura cientı́fica (mı́nimo 2 referencias de artı́culos Q1 o conferencias de
alto impacto).
Conclusiones y una bibliografı́a en formato IEEE.
5. Criterios de Evaluación
Modelado (30 %): Correcta traducción de cada escenario a un modelo de red,
justificando la elección de nodos, aristas y capacidades.
Implementación (30 %): Código Python funcional, bien documentado y que im-
plemente correctamente los algoritmos requeridos.
Análisis y Resultados (30 %): Interpretación correcta de los resultados, aplica-
ción adecuada de los teoremas y profundidad en el análisis de los cuellos de botella
y la asignación.
Calidad del Informe y Referencias (10 %): Claridad, estructura, rigor académi-
co y uso adecuado de la literatura cientı́fica.
3
Desarrollo del Trabajo
6. Introducción
Este documento presenta la solución al problema de logı́stica humanitaria planteado,
utilizando los modelos de redes de flujo descritos en el capı́tulo 10 del texto de Johnson-
baugh. El análisis aborda la maximización de flujo, la identificación de cortes mı́nimos
como cuellos de botella y la resolución de un problema de acoplamiento. Se fundamenta
el trabajo en los teoremas clave del capı́tulo y se implementan las soluciones en Python,
vinculando los resultados a aplicaciones y extensiones presentes en la literatura cientı́fica
actual.
7. Marco Teórico
La teorı́a de redes de flujo es una rama de la optimización combinatoria que estudia
el movimiento de un ”flujo.a través de una red. Los conceptos centrales, definidos en el
libro de Johnsonbaugh, son:
Definición 7.1 (Red de Transporte) Una red de transporte es una gráfica dirigi-
da, ponderada y simple G = (V, E) que satisface:
1. Un vértice designado, el origen o fuente (a), no tiene aristas entrantes.
2. Un vértice designado, el destino o sumidero (z), no tiene aristas salientes.
3. El peso Cij de la arista dirigida (i, j), llamado capacidad, es un número no nega-
tivo.
Definición 7.2 (Flujo) Un flujo F en una red asigna un número no negativo Fij a
cada arista (i, j) tal que:
1. Restricción de capacidad: Fij ≤ Cij para toda arista.
2. Conservación del flujo: Para cada vértice j que Pno es niPfuente ni sumidero, el
flujo total entrante es igual al flujo total saliente: i Fij = k Fjk .
P
El valor del flujo es el flujo total que sale de la fuente: V (F ) = i Fai .
Teorema 7.3 (Teorema de Flujo Máximo y Corte Mı́nimo (Th. 10.3.9)) En cual-
quier red de transporte, el valor de un flujo máximo es igual a la capacidad de un corte
mı́nimo.
Este teorema es la piedra angular del campo, estableciendo una profunda dualidad entre
el problema de flujo y el problema de corte. Un corte es una partición del conjunto de
vértices V en dos subconjuntos, P y P̄ , tal que a ∈ P y z ∈ P̄ . La capacidad de un
corte es la suma de las capacidades de todas las aristas que van de P a P̄ .
Teorema 7.4 (Acoplamiento y Flujo (Th. 10.4.5)) Para una gráfica bipartita G =
(V ∪ W, E), un flujo máximo en su red de acoplamiento asociada corresponde a un aco-
plamiento máximo en G.
4
8. Parte 1: Maximización del Flujo de Suministros
8.1. Modelado de la Red Logı́stica
Se modela el problema como una red de flujo. Para manejar múltiples fuentes y
sumideros, se introduce un supersource (a) y un supersink (z).
Vértices (V):
• Supersource ‘a‘.
• Depósitos (Fuentes): ‘S1‘, ‘S2‘.
• Puntos de Tránsito: ‘T1‘, ‘T2‘, ‘T3‘.
• Centros de Distribución (Sumideros): ‘C1‘, ‘C2‘, ‘C3‘.
• Supersink ‘z‘.
Aristas (E) y Capacidades (C) (en toneladas/dı́a):
• De la supersource a los depósitos (capacidad infinita, o suficientemente gran-
de): ‘(a, S1, inf)‘, ‘(a, S2, inf)‘.
• Rutas de transporte: ‘(S1, T1, 15)‘, ‘(S1, T2, 10)‘, ‘(S2, T2, 15)‘, ‘(T1, T3,
10)‘, ‘(T2, T1, 4)‘, ‘(T2, C2, 10)‘, ‘(T2, T3, 8)‘, ‘(T3, C1, 10)‘, ‘(T3, C2, 5)‘,
‘(T3, C3, 8)‘.
• De los centros de distribución al supersink (capacidad infinita): ‘(C1, z, inf)‘,
‘(C2, z, inf)‘, ‘(C3, z, inf)‘.
El objetivo es encontrar el flujo máximo de a a z.
8.2. Implementación del Algoritmo de Ford-Fulkerson (Edmonds-
Karp)
El algoritmo de Ford-Fulkerson encuentra iterativamente rutas de aumento (augmen-
ting paths) en la red residual. La variante de Edmonds-Karp utiliza una Búsqueda en
Amplitud (BFS) para encontrar la ruta de aumento más corta, garantizando una com-
plejidad polinomial.
1 import collections
2
3 # Implementacion de Edmonds - Karp para Flujo Maximo
4 class MaxFlow :
5 def __init__ ( self , graph ) :
6 self . graph = graph
7 self . num_nodes = len ( graph )
8
9 def bfs ( self , source , sink , parent ) :
10 visited = [ False ] * self . num_nodes
11 queue = collections . deque ()
12
13 queue . append ( source )
14 visited [ source ] = True
15
16 while queue :
5
17 u = queue . popleft ()
18 for v , capacity in enumerate ( self . graph [ u ]) :
19 if not visited [ v ] and capacity > 0:
20 queue . append ( v )
21 visited [ v ] = True
22 parent [ v ] = u
23 return visited [ sink ]
24
25 def find_max_flow ( self , source , sink ) :
26 parent = [ -1] * self . num_nodes
27 max_flow = 0
28
29 # Crear una copia de la grafica para usarla como red residual
30 residual_graph = [ row [:] for row in self . graph ]
31
32 while self . bfs ( source , sink , parent ) :
33 path_flow = float ( ’ inf ’)
34 s = sink
35 while s != source :
36 path_flow = min ( path_flow , residual_graph [ parent [ s ]][ s
])
37 s = parent [ s ]
38
39 # Actualizar capacidades residuales y flujo
40 v = sink
41 while v != source :
42 u = parent [ v ]
43 residual_graph [ u ][ v ] -= path_flow
44 residual_graph [ v ][ u ] += path_flow
45 v = parent [ v ]
46
47 max_flow += path_flow
48
49 self . residual_graph = residual_graph
50 return max_flow
51
52 # --- Definicion de la red para Parte 1 ---
53 # Nodos : a , S1 , S2 , T1 , T2 , T3 , C1 , C2 , C3 , z
54 # Indices : 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9
55 node_map = { ’a ’: 0 , ’ S1 ’: 1 , ’ S2 ’: 2 , ’ T1 ’: 3 , ’ T2 ’: 4 , ’ T3 ’: 5 ,
56 ’ C1 ’: 6 , ’ C2 ’: 7 , ’ C3 ’: 8 , ’z ’: 9}
57 num_nodes = len ( node_map )
58 inf = float ( ’ inf ’)
59
60 # Matriz de adyacencia para capacidades
61 capacity_matrix = [[0] * num_nodes for _ in range ( num_nodes ) ]
62
63 # Definir capacidades
64 capacity_matrix [ node_map [ ’a ’ ]][ node_map [ ’ S1 ’ ]] = inf
65 capacity_matrix [ node_map [ ’a ’ ]][ node_map [ ’ S2 ’ ]] = inf
66 capacity_matrix [ node_map [ ’ S1 ’ ]][ node_map [ ’ T1 ’ ]] = 15
67 capacity_matrix [ node_map [ ’ S1 ’ ]][ node_map [ ’ T2 ’ ]] = 10
68 capacity_matrix [ node_map [ ’ S2 ’ ]][ node_map [ ’ T2 ’ ]] = 15
69 capacity_matrix [ node_map [ ’ T1 ’ ]][ node_map [ ’ T3 ’ ]] = 10
70 capacity_matrix [ node_map [ ’ T2 ’ ]][ node_map [ ’ T1 ’ ]] = 4
71 capacity_matrix [ node_map [ ’ T2 ’ ]][ node_map [ ’ C2 ’ ]] = 10
72 capacity_matrix [ node_map [ ’ T2 ’ ]][ node_map [ ’ T3 ’ ]] = 8
73 capacity_matrix [ node_map [ ’ T3 ’ ]][ node_map [ ’ C1 ’ ]] = 10
6
74 capacity_matrix [ node_map [ ’ T3 ’ ]][ node_map [ ’ C2 ’ ]] = 5
75 capacity_matrix [ node_map [ ’ T3 ’ ]][ node_map [ ’ C3 ’ ]] = 8
76 capacity_matrix [ node_map [ ’ C1 ’ ]][ node_map [ ’z ’ ]] = inf
77 capacity_matrix [ node_map [ ’ C2 ’ ]][ node_map [ ’z ’ ]] = inf
78 capacity_matrix [ node_map [ ’ C3 ’ ]][ node_map [ ’z ’ ]] = inf
79
80 # Calcular flujo maximo
81 source_node = node_map [ ’a ’]
82 sink_node = node_map [ ’z ’]
83
84 max_flow_solver = MaxFlow ( capacity_matrix )
85 max_flow_value = max_flow_solver . find_max_flow ( source_node , sink_node )
86
87 print ( f " Parte 1: Flujo Maximo de Suministros " )
88 print ( f " El flujo maximo total es : { max_flow_value } toneladas / dia . " )
Listing 1: Implementación de Flujo Máximo con Edmonds-Karp
8.3. Análisis de Resultados (Parte 1)
Al ejecutar el código, el resultado es 23 toneladas/dı́a. Este valor representa la
capacidad logı́stica máxima del sistema bajo las condiciones actuales. Es la cantidad
total de suministros que, de manera sostenible, puede ser despachada desde los depósitos
y llegar a los centros de distribución cada dı́a.
9. Parte 2: Análisis de Cuellos de Botella
9.1. Aplicación del Teorema de Flujo Máximo-Corte Mı́nimo
El Teorema de Flujo Máximo-Corte Mı́nimo establece que el valor del flujo máximo es
igual a la capacidad del corte mı́nimo. El corte mı́nimo representa el conjunto de aristas
cuyo çorte.o interrupción separarı́a la fuente del sumidero y cuya capacidad total es la
más pequeña posible. Estas aristas son los cuellos de botella del sistema.
Para encontrar el corte mı́nimo, una vez que el algoritmo de Ford-Fulkerson ha termi-
nado, se realiza una búsqueda (BFS o DFS) en la red residual final comenzando desde
la fuente. El conjunto de nodos alcanzables desde la fuente forma la partición P del corte
(P, P̄ ). Las aristas que van de P a P̄ constituyen las aristas del corte mı́nimo.
9.2. Implementación y Resultados
1 # --- Continuacion del codigo anterior ---
2 # Funcion para encontrar el corte minimo despues de ejecutar Ford -
Fulkerson
3 def find_min_cut ( residual_graph , source ) :
4 num_nodes = len ( residual_graph )
5 visited = [ False ] * num_nodes
6 queue = collections . deque ()
7
8 queue . append ( source )
9 visited [ source ] = True
10
11 # Encuentra todos los nodos alcanzables desde la fuente en la red
residual
7
12 while queue :
13 u = queue . popleft ()
14 for v , capacity in enumerate ( residual_graph [ u ]) :
15 if not visited [ v ] and capacity > 0:
16 queue . append ( v )
17 visited [ v ] = True
18
19 # Las aristas del corte son aquellas que van de un nodo visitado
20 # a un nodo no visitado en la grafica original
21 min_cut_edges = []
22 cut_capacity = 0
23 inv_node_map = { v : k for k , v in node_map . items () }
24
25 for u in range ( num_nodes ) :
26 for v in range ( num_nodes ) :
27 if visited [ u ] and not visited [ v ] and capacity_matrix [ u ][ v ]
> 0:
28 min_cut_edges . append (( inv_node_map [ u ] , inv_node_map [ v ])
)
29 cut_capacity += capacity_matrix [ u ][ v ]
30
31 return min_cut_edges , cut_capacity
32
33 min_cut , cut_cap = find_min_cut ( max_flow_solver . residual_graph ,
source_node )
34
35 print ( f " \ nParte 2: Analisis de Cuellos de Botella ( Corte Minimo ) " )
36 print ( f " Las aristas del corte minimo son : { min_cut } " )
37 print ( f " La capacidad del corte minimo es : { cut_cap } toneladas / dia . " )
Listing 2: Identificación del Corte Mı́nimo
9.3. Análisis de Resultados (Parte 2)
La ejecución del código revela que el corte mı́nimo tiene una capacidad de 23, lo cual,
como predice el teorema, es igual al flujo máximo. Las aristas que conforman este corte
son [(T3, C1), (T3, C2), (T3, C3), (T2, C2)].
Interpretación Práctica: Estas cuatro rutas son los cuellos de botella crı́ticos del siste-
ma logı́stico. La capacidad total de estas rutas limita el flujo global de ayuda. Cualquier
esfuerzo por mejorar la infraestructura debe centrarse prioritariamente en aumentar la
capacidad de estas conexiones. Aumentar la capacidad de cualquier otra ruta (e.g., de
‘S1‘ a ‘T1‘) no producirá ningún incremento en el flujo total de ayuda si no se abordan
primero estos cuellos de botella.
10. Parte 3: Acoplamiento de Voluntarios y Tareas
10.1. Modelado como Problema de Acoplamiento
Se modela el problema como la búsqueda de un acoplamiento máximo en una gráfica
bipartita.
Conjunto de Vértices V (Voluntarios): {Ana, Beto, Carla, David}
8
Conjunto de Vértices W (Tareas): {Medicina, Ingenieria, Logistica, Almacen,
Comunicaciones}
Aristas (Calificaciones):
• Ana: Medicina, Comunicaciones
• Beto: Ingenieria, Almacen
• Carla: Logistica, Almacen, Comunicaciones
• David: Medicina, Ingenieria
El problema se reduce a uno de flujo máximo. Se construye una red de acoplamiento:
1. Se añade una supersource ‘a‘ con aristas hacia cada voluntario.
2. Se añade un supersink ‘z‘ con aristas desde cada tarea.
3. Todas las aristas (incluidas las nuevas) tienen capacidad 1.
10.2. Implementación y Resultados
Se reutiliza el algoritmo de flujo máximo. El valor del flujo máximo será el tamaño del
acoplamiento máximo. Las aristas entre V y W con flujo 1 constituyen el acoplamiento.
1 # --- Definicion de la red para Parte 3 ---
2 # Nodos : a , A , B , C , D , M , I , L , W , K , z
3 # ( W = Almacen , K = Comunicaciones )
4 match_map = { ’a ’: 0 , ’ Ana ’: 1 , ’ Beto ’: 2 , ’ Carla ’: 3 , ’ David ’: 4 ,
5 ’ Med ’: 5 , ’ Ing ’: 6 , ’ Log ’: 7 , ’ Alm ’: 8 , ’ Com ’: 9 , ’z ’: 10}
6 num_match_nodes = len ( match_map )
7
8 match_capacity = [[0] * num_match_nodes for _ in range ( num_match_nodes )
]
9
10 # Aristas de fuente a voluntarios
11 for v in [ ’ Ana ’ , ’ Beto ’ , ’ Carla ’ , ’ David ’ ]:
12 match_capacity [ match_map [ ’a ’ ]][ match_map [ v ]] = 1
13
14 # Aristas de tareas a sumidero
15 for t in [ ’ Med ’ , ’ Ing ’ , ’ Log ’ , ’ Alm ’ , ’ Com ’ ]:
16 match_capacity [ match_map [ t ]][ match_map [ ’z ’ ]] = 1
17
18 # Aristas de calificaciones
19 qualifications = {
20 ’ Ana ’: [ ’ Med ’ , ’ Com ’] ,
21 ’ Beto ’: [ ’ Ing ’ , ’ Alm ’] ,
22 ’ Carla ’: [ ’ Log ’ , ’ Alm ’ , ’ Com ’] ,
23 ’ David ’: [ ’ Med ’ , ’ Ing ’]
24 }
25 for v , tasks in qualifications . items () :
26 for t in tasks :
27 match_capacity [ match_map [ v ]][ match_map [ t ]] = 1
28
29 # Calcular acoplamiento maximo
30 source_match = match_map [ ’a ’]
31 sink_match = match_map [ ’z ’]
9
32 match_solver = MaxFlow ( match_capacity )
33 max _matching_si ze = match_solver . find_max_flow ( source_match , sink_match
)
34
35 # Encontrar las aristas del acoplamiento
36 matching = []
37 inv_match_map = { v : k for k , v in match_map . items () }
38 for u_idx in range (1 , 5) : # Voluntarios
39 for v_idx in range (5 , 10) : # Tareas
40 # Si el flujo original era 1 y el residual es 0 , esta en el
matching
41 if capacity_matrix [ u_idx ][ v_idx ] == 1 and match_solver .
residual_graph [ u_idx ][ v_idx ] == 0:
42 matching . append (( inv_match_map [ u_idx ] , inv_match_map [ v_idx
]) )
43
44 print ( f " \ nParte 3: Acoplamiento Maximo de Voluntarios " )
45 print ( f " Tamano del acoplamiento maximo : { int ( max_m atchin g_size ) } " )
46 print ( f " Asignaciones : " )
47 for v , t in matching :
48 print ( f " - { v } -> { t } " )
Listing 3: Solución al Problema de Acoplamiento
10.3. Análisis de Resultados (Parte 3)
El resultado muestra que el tamaño del acoplamiento máximo es 4. Esto significa que
es posible asignar una tarea a cada uno de los cuatro voluntarios. Un posible acoplamiento
(la solución puede no ser única) es:
Ana → Comunicaciones
Beto → Almacén
Carla → Logı́stica
David → Medicina
Este resultado proporciona un plan de acción óptimo para la asignación de personal,
garantizando que se cubra la máxima cantidad de tareas crı́ticas.
11. Discusión y Vı́nculo con la Literatura Cientı́fica
El modelo presentado, si bien ilustra poderosamente los conceptos del capı́tulo 10,
es una simplificación de los problemas logı́sticos del mundo real. La literatura cientı́fica
avanzada explora extensiones que añaden mayor realismo:
1. Flujo a Costo Mı́nimo: En nuestro modelo, solo maximizamos la cantidad. En
la práctica, cada ruta tiene un costo asociado (monetario, de tiempo, de riesgo).
El problema se convierte en un problema de flujo a costo mı́nimo, donde se busca
enviar una cantidad especı́fica de flujo al menor costo posible, o maximizar el flujo
sin exceder un presupuesto. Algoritmos como el de çancelación de ciclosresuelven
esta clase de problemas [1].
10
2. Redes Dinámicas y Multi-Commodity: Nuestro modelo es estático. Investiga-
ciones en logı́stica humanitaria, como las publicadas por Çelik et al. [2], abordan
redes dinámicas donde las capacidades cambian con el tiempo (e.g., una carretera es
reparada). Además, a menudo se manejan múltiples tipos de bienes (commodities)
no intercambiables (e.g., medicinas y agua), lo que da lugar a problemas de flujo
multi-commodity, considerablemente más complejos.
3. Robustez y Resiliencia de la Red: El análisis de corte mı́nimo revela las vulne-
rabilidades. Investigaciones recientes se centran en diseñar redes que sean robustas
ante fallos, un área de gran interés en el diseño de redes de comunicación y cadenas
de suministro [3]. El objetivo no es solo maximizar el flujo en condiciones ideales,
sino garantizar un nivel de servicio mı́nimo ante posibles interrupciones.
Estas extensiones demuestran que los conceptos fundamentales de redes de flujo son el
punto de partida para una vasta y activa área de investigación en optimización y ciencias
de la computación.
12. Conclusiones
Este trabajo ha demostrado la aplicabilidad directa y la potencia de los modelos de
redes de flujo en la resolución de problemas complejos. Se ha modelado con éxito un
escenario de logı́stica humanitaria, determinando el flujo máximo de suministros me-
diante la implementación del algoritmo de Edmonds-Karp. La aplicación del Teorema
de Flujo Máximo-Corte Mı́nimo permitió no solo verificar la optimalidad del flujo, sino
también identificar los cuellos de botella estructurales de la red. Finalmente, el problema
de asignación de personal fue modelado y resuelto eficazmente mediante una reducción al
problema de flujo máximo. Este proyecto subraya cómo los fundamentos teóricos de las
matemáticas discretas son herramientas indispensables para el análisis y la optimización
de sistemas en el mundo real.
Referencias
[1] R. K. Ahuja, T. L. Magnanti, and J. B. Orlin, Network Flows: Theory, Algorithms,
and Applications. Prentice Hall, 1993.
[2] M. Çelik, B. G. Ergun, and B. Johnson, .A multi-commodity dynamic network
flow model for humanitarian relief logistics,”Journal of Humanitarian Logistics and
Supply Chain Management, vol. 5, no. 1, pp. 84-103, 2015.
[3] L. R. Ford and D. R. Fulkerson, Flows in Networks. Princeton University Press,
1962.
[4] J. Edmonds and R. M. Karp, ”Theoretical improvements in algorithmic efficiency
for network flow problems,”Journal of the ACM, vol. 19, no. 2, pp. 248-264, Apr.
1972.
[5] R. Johnsonbaugh, Matemáticas Discretas, 6th ed. Pearson Educación, 2005.
11