C++算法:有向图访问计数的原理及实现

简介: C++算法:有向图访问计数的原理及实现

题目

现有一个有向图,其中包含 n 个节点,节点编号从 0 到 n - 1 。此外,该图还包含了 n 条有向边。

给你一个下标从 0 开始的数组 edges ,其中 edges[i] 表示存在一条从节点 i 到节点 edges[i] 的边。

想象在图上发生以下过程:

你从节点 x 开始,通过边访问其他节点,直到你在 此过程 中再次访问到之前已经访问过的节点。

返回数组 answer 作为答案,其中 answer[i] 表示如果从节点 i 开始执行该过程,你可以访问到的不同节点数。

2 <= n <= 100000

无自环。

原理分析

如果只有一个连通区域,则有且只有一环。反证法:假定没有环,除源点外,还可以到达n个端点,共n+1个端点,与共有n个端点重复。假定有x个环,则不重复端点数为:1+n-x。当且仅当x为1是,不重复端点数为n。

当有多个连通区域时,任何一个连通区域都有且只有一个环。下面分两步来证明:一,此连通区域必定有环。二,此区域不存在两个或更多的环。

假定此区域的一条边为i0->edges[i0],edges[i0]简称为i1。如果没有环, 则edges[i1](简称为i2)也在此连通区域,edges[i2](简称i3)也在此连通区域,i4.... 。此连通区域的点数无限,和端点数小于等于n矛盾。

由于出度为1,所以进入环后,无法离开环。自然没第二个环。

编码思路

根据拓扑排序,发现那些点在环上。

根据并集查找获取各连通区域。

统计各连通区域在环上的点数。

求环上各点可以到达的点数,就是此环长度(端点数)。

DFS非环上各点可以到达的点数。就是到环的距离+此环的长度。

拓扑排序和并集查找已经封装,可以直接使用。

核心源码

class CTestTS : public CTopSort
{
public:
    // 通过 CTopSort 继承
    virtual void OnDo(int pre, int cur) override
    {
        m_vCycle[cur] = false;
    }
    vector<int> m_vCycle;
};
class Solution {
public:
    vector<int> countVisitedNodes(vector<int>& edges) {
        m_c = edges.size();
        vector<vector<int>> vNeiB(m_c);
        CUnionFind uf(m_c);
        for (int i = 0; i < edges.size(); i++)
        {
            vNeiB[i].emplace_back(edges[i]);
            uf.Union(i, edges[i]);
        }
        m_ts.m_vCycle.assign(m_c, true);        
        m_ts.Init(vNeiB);
        m_vDis.resize(m_c, -1);
        //环可能处于不同的联通区域
        std::unordered_map<int, int> mRegionNode;//各联通区域环的端点数
        for (int i = 0; i < m_c; i++)
        {
            if (m_ts.m_vCycle[i])
            {
                mRegionNode[uf.GetConnectRegionIndex(i)]++;
            }
        }
        for (int i = 0; i < m_c; i++)
        {
            if (m_ts.m_vCycle[i])
            {
                m_vDis[i] = mRegionNode[uf.GetConnectRegionIndex(i)];
            }
        }
        for (int i = 0; i < m_c; i++)
        {
            dfs(i, edges);
        }
        return m_vDis;
    }
    int dfs(int cur,const vector<int>& edges)
    {
        if (-1 != m_vDis[cur])
        {
            return  m_vDis[cur];
        }
        return m_vDis[cur] = dfs(edges[cur], edges) + 1;
    }
    vector<int> m_vDis;
    CTestTS m_ts;
    int m_c;
};

测试用代码

int main()
{
    vector<int> edges = { 1,2,3,4,0 };
    //vector<int> edges = { 1,2,0,0 };
    Solution slu;
    auto res = slu.countVisitedNodes(edges);
}

测试环境

Win10 +VS2022 + C++17

相关下载

源码:可直接运行

https://download.csdn.net/download/he_zhidan/88388717


其它

视频课程

如果你觉得复杂,想从简单的算法开始,可以学习我的视频课程。

https://edu.csdn.net/course/detail/38771

我的其它课程

https://edu.csdn.net/lecturer/6176

测试环境

win7 VS2019 C++17 或Win10 VS2022 Ck++17

相关下载

算法精讲《闻缺陷则喜算法册》doc版

https://download.csdn.net/download/he_zhidan/88348653

相关文章
|
9天前
|
算法 Java 数据库
理解CAS算法原理
CAS(Compare and Swap,比较并交换)是一种无锁算法,用于实现多线程环境下的原子操作。它通过比较内存中的值与预期值是否相同来决定是否进行更新。JDK 5引入了基于CAS的乐观锁机制,替代了传统的synchronized独占锁,提升了并发性能。然而,CAS存在ABA问题、循环时间长开销大和只能保证单个共享变量原子性等缺点。为解决这些问题,可以使用版本号机制、合并多个变量或引入pause指令优化CPU执行效率。CAS广泛应用于JDK的原子类中,如AtomicInteger.incrementAndGet(),利用底层Unsafe库实现高效的无锁自增操作。
理解CAS算法原理
|
3天前
|
存储 算法 安全
基于红黑树的局域网上网行为控制C++ 算法解析
在当今网络环境中,局域网上网行为控制对企业和学校至关重要。本文探讨了一种基于红黑树数据结构的高效算法,用于管理用户的上网行为,如IP地址、上网时长、访问网站类别和流量使用情况。通过红黑树的自平衡特性,确保了高效的查找、插入和删除操作。文中提供了C++代码示例,展示了如何实现该算法,并强调其在网络管理中的应用价值。
|
1天前
|
存储 算法 安全
基于哈希表的文件共享平台 C++ 算法实现与分析
在数字化时代,文件共享平台不可或缺。本文探讨哈希表在文件共享中的应用,包括原理、优势及C++实现。哈希表通过键值对快速访问文件元数据(如文件名、大小、位置等),查找时间复杂度为O(1),显著提升查找速度和用户体验。代码示例展示了文件上传和搜索功能,实际应用中需解决哈希冲突、动态扩容和线程安全等问题,以优化性能。
|
8天前
|
算法 安全 C++
用 C++ 算法控制员工上网的软件,关键逻辑是啥?来深度解读下
在企业信息化管理中,控制员工上网的软件成为保障网络秩序与提升办公效率的关键工具。该软件基于C++语言,融合红黑树、令牌桶和滑动窗口等算法,实现网址精准过滤、流量均衡分配及异常连接监测。通过高效的数据结构与算法设计,确保企业网络资源优化配置与安全防护升级,同时尊重员工权益,助力企业数字化发展。
32 4
|
2月前
|
算法 容器
令牌桶算法原理及实现,图文详解
本文介绍令牌桶算法,一种常用的限流策略,通过恒定速率放入令牌,控制高并发场景下的流量,确保系统稳定运行。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
令牌桶算法原理及实现,图文详解
|
30天前
|
存储 人工智能 缓存
【AI系统】布局转换原理与算法
数据布局转换技术通过优化内存中数据的排布,提升程序执行效率,特别是对于缓存性能的影响显著。本文介绍了数据在内存中的排布方式,包括内存对齐、大小端存储等概念,并详细探讨了张量数据在内存中的排布,如行优先与列优先排布,以及在深度学习中常见的NCHW与NHWC两种数据布局方式。这些布局方式的选择直接影响到程序的性能,尤其是在GPU和CPU上的表现。此外,还讨论了连续与非连续张量的概念及其对性能的影响。
51 3
|
2月前
|
机器学习/深度学习 人工智能 算法
探索人工智能中的强化学习:原理、算法与应用
探索人工智能中的强化学习:原理、算法与应用
|
2月前
|
负载均衡 算法 应用服务中间件
5大负载均衡算法及原理,图解易懂!
本文详细介绍负载均衡的5大核心算法:轮询、加权轮询、随机、最少连接和源地址散列,帮助你深入理解分布式架构中的关键技术。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
5大负载均衡算法及原理,图解易懂!
|
2月前
|
缓存 算法 网络协议
OSPF的路由计算算法:原理与应用
OSPF的路由计算算法:原理与应用
60 4
|
2月前
|
存储 算法 网络协议
OSPF的SPF算法介绍:原理、实现与应用
OSPF的SPF算法介绍:原理、实现与应用
93 3