class Edge(object):
"""边"""
def __init__(self, a, b, weight):
self.a = a
self.b = b
self.weight = weight
def v(self):
return self.a
def w(self):
return self.b
def wt(self):
return self.weight
def other(self, x):
if x == self.a or x == self.b:
if x == self.a:
return self.b
else:
return self.a
def __lt__(self, other):
return self.weight < other.wt()
def __le__(self, other):
return self.weight <= other.wt()
def __gt__(self, other):
return self.weight > other.wt()
def __ge__(self, other):
return self.weight >= other.wt()
def __eq__(self, other):
return self.weight == other.wt()
class DenseGraph(object):
"""有权稠密图 - 邻接矩阵"""
def __init__(self, n, directed):
self.n = n
self.m = 0
self.directed = directed
self.g = [[None for _ in range(n)] for _ in range(n)]
def V(self):
return self.n
def E(self):
return self.m
def addEdge(self, v, w, weight):
if v >= 0 and v < n and w >= 0 and w < n:
if self.hasEdge(v, w):
self.m -= 1
self.g[v][w] = Edge(v, w, weight)
if not self.directed:
self.g[w][v] = Edge(w, v, weight)
self.m += 1
def hasEdge(self, v, w):
if v >= 0 and v < n and w >= 0 and w < n:
return self.g[v][w] != None
class adjIterator(object):
"""相邻节点迭代器"""
def __init__(self, graph, v):
self.G = graph
self.v = v
self.index = 0
def __iter__(self):
return self
def next(self):
while self.index < self.G.V():
if self.G.g[self.v][self.index]:
r = self.G.g[self.v][self.index]
self.index += 1
return r
self.index += 1
raise StopIteration()
class SparseGraph(object):
"""有权稀疏图- 邻接表"""
def __init__(self, n, directed):
self.n = n
self.m = 0
self.directed = directed
self.g = [[] for _ in range(n)]
def V(self):
return self.n
def E(self):
return self.m
def addEdge(self, v, w, weight):
if v >= 0 and v < n and w >= 0 and w < n:
self.g[v].append(Edge(v, w, weight))
if v != w and not self.directed:
self.g[w].append(Edge(w, v, weight))
self.m += 1
def hasEdge(self, v, w):
if v >= 0 and v < n and w >= 0 and w < n:
for i in self.g[v]:
if i.other(v) == w:
return True
return False
class adjIterator(object):
"""相邻节点迭代器"""
def __init__(self, graph, v):
self.G = graph
self.v = v
self.index = 0
def __iter__(self):
return self
def next(self):
if len(self.G.g[self.v]):
if self.index < len(self.G.g[self.v]):
r = self.G.g[self.v][self.index]
self.index += 1
return r
else:
raise StopIteration()
else:
raise StopIteration()
class ReadGraph(object):
"""读取文件中的图"""
def __init__(self, graph, filename):
with open(filename, 'r') as f:
line = f.readline()
line = line.strip('\n')
line = line.split()
v = int(line[0])
e = int(line[1])
if v == graph.V():
lines = f.readlines()
for i in lines:
a, b, w = self.stringstream(i)
if a >= 0 and a < v and b >=0 and b < v:
graph.addEdge(a, b, w)
def stringstream(self, text):
result = text.strip('\n')
result = result.split()
a, b, w = result
return int(a), int(b), float(w)
class IndexMinHeap(object):
"""
最小反向索引堆,出堆不删除data,只删除indexs
"""
def __init__(self, n):
self.capacity = n
self.data = [-1 for _ in range(n)]
self.indexs = []
self.reverse = [-1 for _ in range(n)]
self.count = 0
def size(self):
return self.count
def isEmpty(self):
return self.count == 0
def insert(self, i, item):
self.data[i] = item
self.indexs.append(i)
self.reverse[i] = self.count
self.count += 1
self.shiftup(self.count)
def shiftup(self, count):
while count > 1 and self.data[self.indexs[(count/2)-1]] > self.data[self.indexs[count-1]]:
self.indexs[(count/2)-1], self.indexs[count-1] = self.indexs[count-1], self.indexs[(count/2)-1]
self.reverse[self.indexs[(count/2)-1]] = (count/2)-1
self.reverse[self.indexs[count-1]] = count-1
count /= 2
def extractMin(self):
if self.count > 0:
ret = self.data[self.indexs[0]]
self.indexs[0], self.indexs[self.count-1] = self.indexs[self.count-1], self.indexs[0]
self.reverse[self.indexs[0]] = 0
self.reverse[self.indexs[self.count-1]] = self.count-1
self.reverse[self.indexs[self.count-1]] = -1
self.indexs.pop(self.count-1)
self.count -= 1
self.shiftDown(1)
return ret
def extractMinIndex(self):
if self.count > 0:
ret = self.indexs[0]
self.indexs[0], self.indexs[self.count-1] = self.indexs[self.count-1], self.indexs[0]
self.reverse[self.indexs[0]] = 0
self.reverse[self.indexs[self.count-1]] = self.count-1
self.reverse[self.indexs[self.count-1]] = -1
self.indexs.pop(self.count-1)
self.count -= 1
self.shiftDown(1)
return ret
def shiftDown(self, count):
while 2 * count <= self.count :
j = 2 * count
if j + 1 <= self.count:
if self.data[self.indexs[j]] < self.data[self.indexs[j-1]]:
j += 1
if self.data[self.indexs[count-1]] <= self.data[self.indexs[j-1]]:
break
self.indexs[count-1], self.indexs[j-1] = self.indexs[j-1], self.indexs[count-1]
self.reverse[self.indexs[count-1]] = count-1
self.reverse[self.indexs[j-1]] =j-1
count = j
def getItem(self, i):
if i >=0 and i <= self.count-1:
return self.data[i]
else:
return None
def change(self, i, newItem):
if i >=0:
self.data[i] = newItem
j = self.reverse[i]
self.shiftup(j+1)
self.shiftDown(j+1)
class PrimMST(object):
"""最小生成树"""
def __init__(self, graph):
self.G = graph
self.ipq = IndexMinHeap(self.G.V())
self.edgeTo = [None for _ in range(self.G.V())]
self.marked = [False for _ in range(self.G.V())]
self.mst = []
self.mstWeight = 0
self.visit(0)
while not self.ipq.isEmpty():
v = self.ipq.extractMinIndex()
self.mst.append(self.edgeTo[v])
self.visit(v)
self.mstWeight = sum([i.wt() for i in self.mst])
def visit(self, v):
if not self.marked[v]:
self.marked[v] = True
adj = self.G.adjIterator(self.G, v)
for i in adj:
w = i.other(v)
if not self.marked[w]:
if not self.edgeTo[w]:
self.ipq.insert(w, i.wt())
self.edgeTo[w] = i
elif i.wt() < self.edgeTo[w].wt():
self.edgeTo[w] = i
self.ipq.change(w, i.wt())
def mstEdges(self):
return self.mst
def result(self):
return self.mstWeight