如何解决在元组列表中查找圆形路线
例如:
[(1,2),(3,4),(2,3)]. is OK
但是
[(1,3),1)].
我们可以从1 → 2 → 3 → 1
我怀旧了,想起了我的计算机科学学位,所以我想到了图数据结构。不幸的是,我无法使用 python 找到一个好的实现,我在谷歌上搜索(以及在 stackoverflow 上)找到的所有示例都只是为了找到最短路径。
有什么想法可以实现吗?
解决方法
这里有一个 Python 实现,效果很好(也可以在 Java 和 C++ 中使用,但我只尝试了第一种情况)。 https://www.techiedelight.com/check-given-digraph-dag-directed-acyclic-graph-not/
,如果我理解正确,那么问题在于您何时可以到达起点。为了简单和明确,我将从一个普通的python开始。显而易见的蛮力解决方案是检查数据中每个来源的所有可能目的地。当然,您需要稍微组织一下数据。那么它只是一个链接。下面的代码实现了这种方法。
def get_all_sources(data):
ans = dict()
for src,dst in data:
ans.setdefault(src,set()).add(dst)
return ans
def get_all_possible_destinations(src,all_src,ans=None):
ans = set() if ans is None else ans
for dst in all_src.get(src,set()):
if dst in ans:
continue
ans.add(dst)
get_all_possible_destinations(dst,ans)
return ans
def pipeline_source_by_source(data):
all_src = get_all_sources(data)
for src in all_src:
all_possible_destiations = get_all_possible_destinations(src,all_src)
if src in all_possible_destiations:
print(f"found problem: {src} -> {src}")
break
else:
print('no problems found')
if __name__ == '__main__':
data_list = [
[(1,2)],[(1,2),(2,3)],(3,4),3),1)],[(5,6),(5,7),8),9),(9,10),(10,5)],15)]
]
for idx,data in enumerate(data_list):
print(idx)
pipeline_source_by_source(data)
结果:
0
no problems found
1
no problems found
2
no problems found
3
found problem: 1 -> 1
4
found problem: 5 -> 5
5
no problems found
,
这有点晚了,但提供了更短的解决方案(更少的 Python 行)。其基本原理是构建一个可从源(由源索引)直接到达的目的地字典。然后从任何来源浏览可能的目的地,并将任何已经看到的目的地存储在一个集合中。一旦看到一个新的目的地,就会有一个循环。
Python 代码可以是:
def build_dict(lst):
d = dict()
for src,dst in lst:
if src not in d:
d[src] = []
d[src].append(dst)
return d
def dict_loops(d,start=None,seen=None):
if start is None:
return any(dict_loops(d,elt,None) for elt in d.keys())
if start not in d:
return False
if seen is None:
seen = {start}
for hop in d[start]:
if hop in seen:
return True
if dict_loops(d,hop,seen):
return True
return False
def lst_loops(lst):
return dict_loops(build_dict(lst))
它按预期给出:
>>> lst_loops([(1,3)])
False
>>> lst_loops([(1,1)])
True
>>>
表示第一个列表中没有循环,第二个中至少有一个。
,您可以使用递归生成器函数:
def no_cycles(graph):
def has_cycles(n,s = []):
if n in s:
yield (False,n)
else:
yield (True,n)
yield from [i for a,b in graph for i in has_cycles(b,s+[n]) if a == n]
return all(a for a,_ in has_cycles(graph[0][0]))
graphs = [[(1,15)]]
result = [no_cycles(i) for i in graphs]
输出:
[True,True,False,True]
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。