algorithm-in-python/dataStructure/graph/adjacentList.py

255 lines
6.3 KiB
Python
Raw Normal View History

2018-07-08 23:28:29 +08:00
''' mbinary
#########################################################################
# File : adjacentList.py
# Author: mbinary
# Mail: zhuheqin1@gmail.com
2019-01-31 12:09:46 +08:00
# Blog: https://mbinary.xyz
2018-07-08 23:28:29 +08:00
# Github: https://github.com/mbinary
# Created Time: 2018-04-26 10:33
# Description:
#########################################################################
'''
2019-05-23 23:51:44 +08:00
from collections import Iterable, deque
2018-07-08 23:28:29 +08:00
class vertex:
2019-05-23 23:51:44 +08:00
def __init__(self, mark, firstEdge=None, val=None):
2018-07-08 23:28:29 +08:00
self.mark = mark
self.val = val
self.firstEdge = firstEdge
self.isVisited = False
2019-05-23 23:51:44 +08:00
2018-07-08 23:28:29 +08:00
def __str__(self):
2019-05-23 23:51:44 +08:00
return 'V' + str(self.mark)
2018-07-08 23:28:29 +08:00
def __repr__(self):
return str(self)
2019-05-23 23:51:44 +08:00
2018-07-08 23:28:29 +08:00
class edge:
2019-05-23 23:51:44 +08:00
def __init__(self, adjVertexs, weight=1, nextEdge=None):
2018-07-08 23:28:29 +08:00
'''adjVertexs:tuple(v.mark,u.mark)'''
self.weight = weight
self.adjVertexs = adjVertexs
self.nextEdge = nextEdge
self.isVisted = False
2019-05-23 23:51:44 +08:00
def __add__(self, x):
return self.weight + x
def __radd__(self, x):
return self + x
def __getitem__(self, k):
if k != 0 or k != 1: raise IndexError
2018-07-08 23:28:29 +08:00
return self.adjVertexs[k]
2019-05-23 23:51:44 +08:00
2018-07-08 23:28:29 +08:00
def __str__(self):
2019-05-23 23:51:44 +08:00
return '--' + str(self.weight) + '--'
2018-07-08 23:28:29 +08:00
def __repr__(self):
return str(self)
2019-05-23 23:51:44 +08:00
2018-07-08 23:28:29 +08:00
@property
def v(self):
return self.adjVertexs[0]
2019-05-23 23:51:44 +08:00
2018-07-08 23:28:29 +08:00
@property
def u(self):
return self.adjVertexs[1]
2019-05-23 23:51:44 +08:00
2018-07-08 23:28:29 +08:00
class graph:
2019-05-23 23:51:44 +08:00
def __init__(self):
2018-07-08 23:28:29 +08:00
self.vertexs = {}
self.edges = {}
2019-05-23 23:51:44 +08:00
def __getitem__(self, i):
2018-07-08 23:28:29 +08:00
return self.vertexs[i]
2019-05-23 23:51:44 +08:00
def __setitem__(selfi, x):
self.vertexs[i] = x
2018-07-08 23:28:29 +08:00
def __iter__(self):
return iter(self.vertexs)
2019-05-23 23:51:44 +08:00
2018-07-08 23:28:29 +08:00
def __bool__(self):
2019-05-23 23:51:44 +08:00
return len(self.vertexs) != 0
def addVertex(self, vertexs):
2018-07-08 23:28:29 +08:00
'''vertexs is a iterable or just a mark that marks the vertex,whichc can be every imutable type'''
2019-05-23 23:51:44 +08:00
if not isinstance(vertexs, Iterable): vertexs = [vertexs]
2018-07-08 23:28:29 +08:00
for i in vertexs:
2019-05-23 23:51:44 +08:00
if not isinstance(i, vertex) and i not in self.vertexs:
self.vertexs[i] = vertex(i)
if isinstance(i, vertex) and i not in self.vertexs:
self.vertexs[i.mark] = i
2018-07-08 23:28:29 +08:00
2019-05-23 23:51:44 +08:00
def __getVertex(self, v):
if not isinstance(v, vertex):
2018-07-08 23:28:29 +08:00
if v not in self.vertexs:
2019-05-23 23:51:44 +08:00
self.vertexs[v] = vertex(v)
2018-07-08 23:28:29 +08:00
return self.vertexs[v]
return v
2019-05-23 23:51:44 +08:00
def addEdge(self, v, u, weight=1):
2018-07-08 23:28:29 +08:00
v = self.__getVertex(v)
u = self.__getVertex(u)
2019-05-23 23:51:44 +08:00
arc = self.findEdge(v, u)
if arc != None:
return #examine that if v,u have been already connected
vertexs = (v, u)
newEdge = edge(vertexs, weight)
2018-07-08 23:28:29 +08:00
self.edges[vertexs] = newEdge
2019-05-23 23:51:44 +08:00
if v.firstEdge == None:
v.firstEdge = newEdge
2018-07-08 23:28:29 +08:00
else:
2019-05-23 23:51:44 +08:00
arc = v.firstEdge.nextEdge
v.firstEdge = newEdge
def findEdge(self, v, u):
2018-07-08 23:28:29 +08:00
v = self.__getVertex(v)
u = self.__getVertex(u)
arc = v.firstEdge
2019-05-23 23:51:44 +08:00
while arc != None and u not in arc:
2018-07-08 23:28:29 +08:00
arc = arc.nextEdge
2019-05-23 23:51:44 +08:00
if arc != None: return arc
2018-07-08 23:28:29 +08:00
arc = u.firstEdge
2019-05-23 23:51:44 +08:00
while arc != None and v not in arc:
2018-07-08 23:28:29 +08:00
arc = arc.nextEdge
return arc
2019-05-23 23:51:44 +08:00
def delEdge(self, v, u):
if not isinstance(v, vertex): v = self.vertexs[v]
if not isinstance(u, vertex): u = self.vertexs[u]
if u in v.firstEdge:
v.firstEdge = v.firstEdge.nextEdge
2018-07-08 23:28:29 +08:00
else:
arc = v.firstEdge
2019-05-23 23:51:44 +08:00
while arc.nextEdge != e:
2018-07-08 23:28:29 +08:00
arc = arc.nextEdge
2019-05-23 23:51:44 +08:00
if arc != None: arc.nextEdge = arc.nextEdge.nextEdge
2018-07-08 23:28:29 +08:00
else:
2019-05-23 23:51:44 +08:00
if v in u.firstEdge:
u.firstEdge = u.firstEdge.nextEdge
2018-07-08 23:28:29 +08:00
else:
arc = u.firstEdge
2019-05-23 23:51:44 +08:00
while arc.nextEdge != e:
2018-07-08 23:28:29 +08:00
arc = arc.nextEdge
arc.nextEdge = arc.nextEdge.nextEdge
2019-05-23 23:51:44 +08:00
del self.edges[(v, u)]
2018-07-08 23:28:29 +08:00
def revisit(self):
for i in self.vertexs.values():
i.isVisited = False
for i in self.edges.values():
i.isVisited = False
2019-05-23 23:51:44 +08:00
2018-07-08 23:28:29 +08:00
def __str__(self):
2019-05-23 23:51:44 +08:00
arcs = list(self.edges.keys())
arcs = [str(i[0]) + str(self.edges[i]) + str(i[1]) for i in arcs]
s = '\n'.join(arcs)
2018-07-08 23:28:29 +08:00
return s
2019-05-23 23:51:44 +08:00
2018-07-08 23:28:29 +08:00
def __repr__(self):
return str(self)
2019-05-23 23:51:44 +08:00
def minPath(self, v, u):
if v not in self or u not in self: return -1
v = self.__getVertex(v)
u = self.__getVertex(u)
q = deque([v])
last = {i: None for i in self.vertexs.values()}
2018-07-08 23:28:29 +08:00
last[v] = 0
2019-05-23 23:51:44 +08:00
ds = {i: 1000000 for i in self.vertexs.values()}
ds[v] = 0
while len(q) != 0:
2018-07-08 23:28:29 +08:00
nd = q.popleft()
2019-05-23 23:51:44 +08:00
nd.isVisited = True
2018-07-08 23:28:29 +08:00
arc = nd.firstEdge
2019-05-23 23:51:44 +08:00
while arc != None:
tgt = None
if arc.v == nd:
2018-07-08 23:28:29 +08:00
tgt = arc.u
2019-05-23 23:51:44 +08:00
else:
tgt = arc.v
tmp = ds[nd] + arc
if ds[tgt] > tmp:
ds[tgt] = tmp
2018-07-08 23:28:29 +08:00
last[tgt] = nd
2019-05-23 23:51:44 +08:00
if not tgt.isVisited: q.append(tgt)
2018-07-08 23:28:29 +08:00
'''
cur = u
while cur !=v:
print(str(cur)+'<---',end='')
cur =last[cur]
print(str(v))
'''
return ds[u]
2019-05-23 23:51:44 +08:00
2018-07-08 23:28:29 +08:00
def hasCircle(self):
pass
2019-05-23 23:51:44 +08:00
2018-07-08 23:28:29 +08:00
def display(self):
print('vertexs')
for i in self.vertexs:
print(i)
print('edges')
for i in self.edges:
2019-05-23 23:51:44 +08:00
arc = self.edges[i]
print(str(arc.v) + str(arc) + str(arc.u))
if __name__ == '__main__':
n = int(input())
while n > 0:
cities = int(input())
n -= 1
g = graph()
li = {}
2018-07-08 23:28:29 +08:00
for i in range(cities):
2019-05-23 23:51:44 +08:00
li[input()] = i + 1
arc = int(input())
2018-07-08 23:28:29 +08:00
for j in range(arc):
2019-05-23 23:51:44 +08:00
s = input().split(' ')
g.addEdge(i + 1, int(s[0]), int(s[1]))
ct = int(input())
for i in range(ct):
2018-07-08 23:28:29 +08:00
line = input()
2019-05-23 23:51:44 +08:00
line = line.split(' ')
v, u = li[line[0]], li[line[1]]
print(g.minPath(v, u))
2018-07-08 23:28:29 +08:00
g.revisit()
#http://www.spoj.com/submit/SHPATH/id=20525991
'''
1
4
gdansk
2
2 1
3 3
bydgoszcz
3
1 1
3 1
4 4
torun
3
1 3
2 1
4 1
warszawa
2
2 4
3 1
2
gdansk warszawa
bydgoszcz warszawa
V4<---V3<---V2<---V1
3
V4<---V3<---V2
2
>>>
'''