首页 > 编程语言 >有向图访问计数的原理及C++实现

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

时间:2023-10-19 12:04:52浏览次数:28  
标签:vector 有向图 cur vDis int C++ 计数 edges 端点


题目

现有一个有向图,其中包含 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

相关下载

源码:可直接运行


doc格式:方便查阅

【免费】闻缺陷则喜之算法册C++实现资源

更多算法见:

结构与算法_闻缺陷则喜何志丹的博客

标签:vector,有向图,cur,vDis,int,C++,计数,edges,端点
From: https://blog.51cto.com/u_15724537/7934115

相关文章

  • Windows下VC++编译器32位memcpy、memmove函数汇编代码详解
    整理者:赤勇玄心行天道QQ号:280604597微信号:qq280604597QQ群:511046632博客:www.cnblogs.com/gaoyaguo  blog.csdn.net/cyz7758520?type=blog大家有什么不明白的地方,或者想要详细了解的地方可以联系我,我会认真回复的!你可以随意转载,无需注明出处!写文档实属不易,我希望大家能支......
  • 深入实践C++11智能指针
    目录概念一、std::auto_ptr二、std::unique_ptr常用函数自定义智能指针对象持有的资源的释放函数三、std::shared_ptr常用函数四、std::enable_shared_from_this五、std::weak_ptr常用函数智能指针使用注意事项智能指针的简单实现概念C/C++语言最为人所诟病的特性之一就是......
  • C++常见入门题题解
    前言因为本人目前比较菜,所以给出的题解都是按照自己的学习进度来的,所以难度是一个循序渐进的过程,由于本人水平有限,望读者能够指出谬误,共同进步。回文数输出#include<bits/stdc++.h>//万能头usingnamespacestd;intmain(void){vector<int>font;//定义一个整型的向......
  • C++模板笔记
    参考文章:https://juejin.cn/post/7078530622527897631模板是C++的泛型编程机制,这种机制可以最大程度复用代码并且不会增加运行时开销模板分为函数模板和类模板函数模板函数模板是对函数的参数进行泛型化,传递给模板函数的类型实参可以是类,也可以是整型值,还可以是模板名比如://......
  • Qt/C/C++ 项目工程架构搭建设计经验
    摘要  独立负责一个Qt项目和经过前辈的教导后的一些架构搭建感悟,其中的各种理念对其他语言开发的项目也能有一定的互通,能带来更舒适的开发体验,谨代表个人开发的经验之谈,有需要的小伙伴酌情获取,辩证思考。也欢迎小伙伴们在评论区纠错补充。  关键词:C/C++、Qt、搭建框架、更......
  • 关于 K 维空间中整点之间曼哈顿距离最短路径计数问题
    约定\(K\)维空间中,整点的坐标以\(K\)个整数表示,形如\[Point\left(X_1,X_2,\cdots,X_k\right)\]定义两个点的曼哈顿距离为每一维坐标差的绝对值之和,记为\[MD\left(A,B\right)=\sum_{i=1}^{K}\left|{X_{i_A}-X_{i_B}}\right|\]定义两个点\(A\),\(B\)相邻当且仅当......
  • 您需要了解的有关下一个MISRA®标准的信息:MISRA C++ 2023®简介
    我们在直播课中讲解过MISRAC通识及实践(请看VCR),今天我们来探讨一下MISRAC++:2023~ 【北汇信息|MISRAC通识及实践】 MISRAC++:2023®是广受期待的MISRAC++®标准的下一个版本,将于今年晚些时候发布。新版本将整合AUTOSARC++14指南,并支持C++的最新版本。 MISRA®是......
  • 学习C++
    概述:C++的基础语法主要包括变量、常量、数据类型、运算符、控制流语句等。下面分别进行介绍。变量和常量:变量是程序中用于存储数据的标识符,可以改变其值。在C++中,变量必须先声明后使用,声明的语法格式为“数据类型变量名”。例如,声明一个整型变量:inta。常量是在程序中不能改变......
  • 有向图转强连通图最少加边数
    原文链接问题描述对于一有向图,若需要保证任选一点即可走到其它所有点,询问最少需要加多少条有向边结论对于一有向图,若其对应DAG中入度为0的点数为$p$,出度为0的点数为$q$,则答案数为$max(p,q)$证明:$p\leqq$和$p\geqq$的证明过程类似,这里仅说明$p\leqq$的证明过程当$......
  • C++ 获取文件信息(Linux)
    stat函数头文件:#include<sys/stat.h>intstat(constchar*restrictpathname,structstat*restrictbuf);第一个参数pathname:文件名,需要获取该文件的信息第二个参数buf:stat函数将pathname对应的文件信息,填入buf指向的stat结构中返回值:0成功;-1出错structstat{......