这一题的话由于每一个点都有一个输出的点,因此最终任意一条线路都一定会落到一个环当中。
因此,这里必然只会有情况:
当然,具体到整张图当中,就可能会更加复杂一点,具体来说,可能会有:
但无论如何,我们只需要对每一个部分独立进行考察就行。唯一需要注意的是:
而如果某一个点在多个子图当中都有涉及,他们的结果必然是相同的,因此我们可以复用对应的记过。
因此,我们事实上只需要考察任意独立子图的count即可,而这其中,我们又可以之考察第二种情况,即一条线段进入到一个环的情况,因为前者可以视为后者的一个特例。
此时,我们很容易可以得到一条完整的线路,此时,我们就可以得到环的长度了,对于环上的任意一个点,其能够遍历的点就是环的长度,然后对于线段上的点,我们只需要将环的长度加上对应的线段尾部的长度即可。
而如果有另一个子图进入了某个已经被考察过的点,那么我们事实上只要将前面所有的点到该点的距离加上这个点所能遍历的点的数目即可得到前面个点能够遍历的点的个数。
给出最终的python代码实现如下:
class Solution:
def countVisitedNodes(self, edges: List[int]) -> List[int]:
n = len(edges)
res = [-1 for _ in range(n)]
def scan(u):
nonlocal res
if res[u] != -1:
return
visited = {}
nodes = []
idx = 0
while u not in visited and res[u] == -1:
visited[u] = idx
nodes.append(u)
idx += 1
u = edges[u]
if res[u] == -1:
pre = visited[u]
loop = idx - pre
for u in nodes[pre:]:
res[u] = loop
for i, u in enumerate(nodes[:pre]):
res[u] = loop + pre-i
else:
s = res[u]
l = len(nodes)
for i, u in enumerate(nodes):
res[u] = s + l-i
return
in_nodes = set(edges)
starts = [i for i in range(n) if i not in in_nodes]
for i, u in enumerate(starts):
scan(u)
for u in range(n):
if res[u] == -1:
scan(u)
return res
提交代码评测得到:耗时1542ms,占用内存44.7MB。