# -*- coding: utf-8 -*-
class Edge(object):
"""
定义有向边Edge类
source: 源结点
target: 目标结点
capacity: 边的容量
返回值格式: source->target:capacity
"""
def __init__(self, u, v, w):
self.source = u #源结点
self.target = v #目标结点
self.capacity = w #容量
def __repr__(self):
return "%s->%s:%s" % (self.source, self.target, self.capacity)
class FlowNetwork(object):
"""
定义流网络图FlowNetwork类
adj[vertex]: 以vertex为源结点的所有边的集合
flow[edge]: 有向边edge的流量
"""
def __init__(self):
self.adj = {}
self.flow = {}
def add_vertex(self, vertex): #向图中加入结点vertex
self.adj[vertex] = []
def get_edges(self, v): #获取以v为源结点的所有边
return self.adj[v]
def add_edge(self, u, v, w=0): #向图中加入以u为源结点,以v为目标结点,w为容量的边
if u == v:
raise ValueError("u == v")
edge = Edge(u,v,w) #正向边,以u为源结点
redge = Edge(v,u,0) #反向边,以v为源结点
edge.redge = redge
redge.redge = edge
self.adj[u].append(edge)
self.adj[v].append(redge)
self.flow[edge] = 0 #初始流量都设置为0
self.flow[redge] = 0
def find_path(self, source, target, path): #寻找增广路径
if source == target:
return path
for edge in self.get_edges(source):
residual = edge.capacity - self.flow[edge]
if residual > 0 and edge not in path:
result = self.find_path(edge.target, target, path + [edge])
if result != None:
return result
def max_flow(self, source, target):
path = self.find_path(source, target, [])
while path != None: #当找不到增广路径时,根据最大流最小割定理,此时网络达到最大流
residuals = [edge.capacity - self.flow[edge] for edge in path] #path的残存流量
flow = min(residuals)
for edge in path:
self.flow[edge] += flow #为每条边注入残存流量
self.flow[edge.redge] -= flow #为反向边注入反向流量
path = self.find_path(source, target, [])
return sum(self.flow[edge] for edge in self.get_edges(source))
if __name__ == '__main__':
g = FlowNetwork()
Persons = {'Mike', 'Alice', 'Bob', 'Tom', 'John'}
Jobs = {'Work1', 'Work2', 'Work3', 'Work4'}
g.add_vertex('s') #增加虚拟源点's'
g.add_vertex('t') #增加虚拟汇点't'
for person in Persons:
g.add_vertex(person)
g.add_edge('s', person, 1)
for job in Jobs:
g.add_vertex(job)
g.add_edge(job, 't', 1)
g.add_edge('Mike', 'Work1', 2**32-1)
g.add_edge('Alice', 'Work1', 2**32-1)
g.add_edge('Alice', 'Work2', 2**32-1)
g.add_edge('Bob', 'Work3', 2**32-1)
g.add_edge('Tom', 'Work1', 2**32-1)
g.add_edge('Tom', 'Work3', 2**32-1)
g.add_edge('Tom', 'Work4', 2**32-1)
g.add_edge('John', 'Work3', 2**32-1)
g.add_edge('John', 'Work4', 2**32-1)
print ('最大匹配数如下:')
print (g.max_flow('s','t'))
print ('流网络如下:')
print (g.flow)