我正在处理由邻接表示法给出的有向图。换句话说,图G将由一个字典表示,该字典的键是顶点,其值是字典,其键是顶点的邻居,其值可以分配给1。给定两个顶点u,v图G在u到v之间可能有一条边,反之亦然。但是,可能在两个方向上都有一条边缘。
我创建了一个名为reachable_vertices的函数,该函数将使用图形G和顶点v作为输入,并返回可以从v到达的G中所有顶点的列表。如果可以通过v到达顶点w,则意味着有一个链v→v1→v2 ...→w,从链中每个顶点到紧接其后的顶点都有一条边。顶点v不必具有特定的类型,例如int或string,它可以是这两种类型中的任一种,它只需要是表示图G的字典中的键即可。
我定义了一个名为cfb_graph的函数,该函数不带参数。我将文件cfb2010.csv(下面的链接)形成了有向图,方法是将团队视为顶点并仅在team1击败team2时在team1和team2之间建立优势。 数据集链接= https://drive.google.com/open?id=1ZgNjH_QE7if1xHMfRU2-ebd9bNpL2E3d
cfb_graph将返回给出此表示形式的字典。
我能够在下面的代码中找到以下问题: 一世。从奥本无法到达哪些团队。将它们存储在列表中。 ii。从巴黎圣母院可以到达哪些团队。将它们存储在列表中。 iii。无法从阿拉巴马州到达哪些团队。将它们存储在列表中。
我正在处理以下代码:
def reachable(G, v, setA): # This function checks if it's possible to reach w from v
setA|={v}
try:
for w in set(G[v])-setA:reachable(G,w,setA)
except KeyError:
donothing = 0
return setA
## 2a ##
def reachable_vertices(G, v):
setA=set()
setA|={v}
try:
for n in set(G[v])-setA:reachable(G,n,setA)
except KeyError:
donothing = 0
return setA
def cfb_graph():
svertex = []
evertex = []
count= 0
file = open("cfb2010.csv","r")
for line in file:
fields = line.split(",")
if fields[5].replace("\n", "") == 'W':
svertex.append(fields[1])
evertex.append(fields[2])
if count == 0:
count = count +1
graph = {}
for i in range(len(svertex)):
v = svertex[i]
if v in graph:
graph[v] |= set([evertex[i]])
else:
graph[v] = set([evertex[i]])
for key, value in graph.items():
graph[key] = dict.fromkeys(value,1)
return(graph)
######Part 2 c############
auburn_answer = list(set(cfb_graph().keys()).difference(set(reachable_vertices(cfb_graph(), "Auburn"))))
notre_dame_answer = reachable_vertices(cfb_graph(), "Notre Dame")
alabama_answer = list(set(cfb_graph().keys()).difference(set(reachable_vertices(cfb_graph(), "Alabama"))))
尤其是对于每个顶点,我想返回一个字典,其中的键是可到达的顶点,其值将在下面描述。如果从顶点v可以到达顶点w,则存在从v到w的路径。返回的字典中与w对应的值将是在从v到w的某个路径中紧随其后的顶点。如果我使用队列方法,则w的值将是while循环中w是u的邻居的第一个顶点u。
此外,我想定义一个名为path的函数,该函数将图形G和两个顶点v和w作为输入。如果w可从v到达,它将返回一个顶点列表,其第一个元素为v,最后一个元素为w,其他顶点是从v到w的遍历顺序。如果没有路径,我应该返回None。我可能想使用上面定义的功能。
答案 0 :(得分:0)
我想快速而强大的图形处理库networkx将为您提供很多帮助。它具有大量的各种算法,因此您不能手动实现它,而只能在代码中使用函数调用。
我构建了一个小的工作流程,该流程可以复制您的所有功能并解决您的问题:
# Imports
import networkx as nx
import csv
# Load CSV file and construct the directed graph
G = nx.DiGraph()
with open('cfb2010.csv', 'r') as f:
sreader = csv.reader(f, delimiter=',')
for line in sreader:
if line[-1] != 'W':
continue
G.add_node(line[1])
G.add_node(line[2])
G.add_edge(line[1], line[2])
# Get all nodes
all_nodes = set(G.nodes())
# Get nodes that can be reached from the particular node
notredame_nodes = set(nx.bfs_tree(G, 'Notre Dame').nodes())
alabama_nodes = set(nx.bfs_tree(G, 'Alabama').nodes())
auburn_nodes = set(nx.bfs_tree(G, 'Auburn').nodes())
# Construct lists of nodes you need
print(all_nodes - alabama_nodes)
print(all_nodes - auburn_nodes)
print(notredame_nodes)
Networkx还具有一个与您的函数称为path 函数相同的函数:
print(nx.shortest_path(G, 'Florida', 'Illinois'))
['Florida', 'Penn St', 'Michigan', 'Illinois']
P.S。可达节点的构造使用BFS algorithm。