• Leetcode 2876. Count Visited Nodes in a Directed Graph


    1. 解题思路

    这一题的话由于每一个点都有一个输出的点,因此最终任意一条线路都一定会落到一个环当中。

    因此,这里必然只会有情况:

    1. 一个完整的环
    2. 一条线段然后进入到一个环当中

    当然,具体到整张图当中,就可能会更加复杂一点,具体来说,可能会有:

    1. 一张图当中包含多个独立的环等完全隔离的独立子图;
    2. 可能有多条线段进入到同一个环当中甚至出现分叉线段;

    但无论如何,我们只需要对每一个部分独立进行考察就行。唯一需要注意的是:

    1. 对于完整的环,从任意节点出发都会得到相同的结果;
    2. 如果是一条线段然后进入一个环的情况,我们必须从线段的起点出发。

    而如果某一个点在多个子图当中都有涉及,他们的结果必然是相同的,因此我们可以复用对应的记过。

    因此,我们事实上只需要考察任意独立子图的count即可,而这其中,我们又可以之考察第二种情况,即一条线段进入到一个环的情况,因为前者可以视为后者的一个特例。

    此时,我们很容易可以得到一条完整的线路,此时,我们就可以得到环的长度了,对于环上的任意一个点,其能够遍历的点就是环的长度,然后对于线段上的点,我们只需要将环的长度加上对应的线段尾部的长度即可。

    而如果有另一个子图进入了某个已经被考察过的点,那么我们事实上只要将前面所有的点到该点的距离加上这个点所能遍历的点的数目即可得到前面个点能够遍历的点的个数。

    2. 代码实现

    给出最终的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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    提交代码评测得到:耗时1542ms,占用内存44.7MB。

  • 相关阅读:
    【EF Core】实体的主、从关系
    Linux CentOS7 vim多文件编辑
    dds:subscribe
    k8s--基础--22.11--storageclass--类型--Azure 文件
    系统架构师备考倒计时12天(每日知识点)
    c++的引用和指针
    包装机(栈和队列的应用)
    极米Z6X Pro值得购买吗?这篇评测告诉你
    基于C51实现按键控制
    【算法leetcode】1051. 高度检查器(rust和go)
  • 原文地址:https://blog.csdn.net/codename_cys/article/details/133466624