热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

stronglyConnectedComponents强联通分量求法kosarajutarjangabow并查集

1强联通分量解释SCC(stronglyConnectedComponents)对于G(v,e)的一个子图中,其任何两个顶点都存在一个path相互到达;2图的拓扑

1 强联通分量解释

SCC(stronglyConnectedComponents) 对于G(v, e)的一个子图中,其任何两个顶点都存在一个path相互到达;

2 图的拓扑排序

拓扑排序的核心思路还是利用深度优先搜索,排序的基本思想为深度优先搜索正好只会访问每个顶点一次,如果将dfs的参数顶点保存在一个数据结构中,遍历这个数据结构就能访问图中的所有顶点,而遍历的顺序取决于这个数据结构的性质以及是在递归调用之前还是递归调用之后保存。

  • 1 前序: 在递归调用之前将顶点加入队列 —- pre()方法
  • 2 后序: 在递归调用之后将顶点加入队列 —- post()方法
  • 3 逆后序: 在递归调用之后将顶点压入栈 —- reversePost()方法
    这里给出一个逆后序的例子:
    https://cdn.jsdelivr.net/gh/xychen5/blogImgs@main/imgs/强联通分量.77kjmz93ddc0.png
    其逆后序得到的一个栈为:(右侧为栈顶,代表最晚完成访问的节点) 6 4 2 5 3 1

逆后序获得代码:

public class DepthFirstOrder {private boolean[] marked;private Queue<Integer> pre; //所有顶点的前序排列private Queue<Integer> post; //所有顶点的后序排列private Stack<Integer> reversePost; //所有顶点的逆后序排列public DepthFirstOrder(Digraph G){pre &#61; new Queue<Integer>();post &#61; new Queue<Integer>();reversePost &#61; new Stack<Integer>();marked &#61; new boolean[G.V()];for(int v &#61;0;v<G.V();v&#43;&#43;)if(!marked[v]) dfs(G,v);}private void dfs(Digraph G,int v){pre.enqueue(v);marked[v] &#61; true;for(int w:G.adj(v))if(!marked[w])dfs(G,w);post.enqueue(v);reversePost.push(v);}public Iterable<Integer> pre(){return pre;}public Iterable<Integer> post(){return post;}public Iterable<Integer> reversePost(){return reversePost;}}

3 求解算法


3.1 kosaraju算法

https://en.wikipedia.org/wiki/Kosaraju%27s_algorithm 伪代码:

  1. For each vertex u of the graph, mark u as unvisited. Let L be empty.
  2. For each vertex u of the graph do Visit(u), where Visit(u) is the recursive subroutine:
    If u is unvisited then:
    1. Mark u as visited.
    2. For each out-neighbour v of u, do Visit(v).
    3. Prepend u to L.
    Otherwise do nothing.
  3. For each element u of L in order, do Assign(u,u) where Assign(u,root) is the recursive subroutine:
    If u has not been assigned to a component then:
    1. Assign u as belonging to the component whose root is root.
    2. For each in-neighbour v of u, do Assign(v,root).
    Otherwise do nothing.

换句话说&#xff1a;
主要就是2次dfs&#xff1a;

  • 1 获得G的逆图G’&#xff0c;对G做一遍dfs获得其逆后序的顶点访问序列
  • 2 对于逆后序顶点访问序列&#xff0c;重复2.1即可
    • 2.1 将最晚完成访问的顶点&#xff0c;在G’中访问&#xff0c;能够一遍到达的那些顶点&#xff0c;就是目标的连通分量&#xff0c;将相关顶点在逆后序访问序列中移除即可

3.2 Tarjan算法&#xff08;待续&#xff09;

参考&#xff1a; https://www.cnblogs.com/wuchanming/p/4138705.html

3.3 Gabow算法(待续)

参考&#xff1a; https://www.cnblogs.com/wuchanming/p/4138705.html

具体的例子&#xff1a;

4 实际题解


4.1 针对无向图连通分量求解

该解题方案实际上为有向图强联通分量求解的一个子集&#xff0c;无向图即为顶点和顶点之间的边均为双向边。
这里以kosaraju算法为例:

  • 1 对于有向图&#xff0c;一开始我们需要获取dfs的逆序遍历栈&#xff0c;原因是&#xff0c;在第二次dfs也就是逆图中的遍历我们可以总是用最晚完成遍历的点去遍历&#xff0c;如此依赖&#xff0c;这样的一个遍历就能得到一个连通分量。
  • 2 但是针对无向图&#xff0c;不需要这样&#xff0c;因为遍历到不能拓展新的节点&#xff0c;我们就获取到了一个连通分量。

https://leetcode-cn.com/problems/number-of-provinces/
其解法如下&#xff1a;

class Solution {
public:void dfs(vector<vector<int>>& g, vector<int>& reversePost, vector<bool>& vis, int tarV) {vis[tarV] &#61; true;for(int j &#61; 0; j < g.size(); &#43;&#43;j) {if(g[tarV][j] !&#61; 0) {if(!vis[j]) {dfs(g, reversePost, vis, j);}} }reversePost.emplace_back(tarV);}int findCircleNum(vector<vector<int>>& isConnected) {// 获取逆图int n &#61; isConnected.size();vector<vector<int>> revIsConnected(isConnected);// 由于不是针对有向图&#xff0c;故不需要这一步// 获取逆序vector<bool> vis(n, false);vector<int> reversePost;// dfs(isConnected, reversePost, vis, 0);// 直接任选一点遍历&#xff0c;看有几个连通分量即可int ans &#61; 0; for(int j &#61; 0; j < isConnected.size(); &#43;&#43;j) {if(!vis[j]) {dfs(isConnected, reversePost, vis, j);ans &#43;&#43;;} }return ans;}
};// 顺便给一个并查集解法&#xff1a;
class Solution {public int findCircleNum(int[][] isConnected) {int provinces &#61; isConnected.length;int[] parent &#61; new int[provinces];for (int i &#61; 0; i < provinces; i&#43;&#43;) {parent[i] &#61; i;}for (int i &#61; 0; i < provinces; i&#43;&#43;) {for (int j &#61; i &#43; 1; j < provinces; j&#43;&#43;) {if (isConnected[i][j] &#61;&#61; 1) {union(parent, i, j);}}}int circles &#61; 0;for (int i &#61; 0; i < provinces; i&#43;&#43;) {if (parent[i] &#61;&#61; i) {circles&#43;&#43;;}}return circles;}public void union(int[] parent, int index1, int index2) {parent[find(parent, index1)] &#61; find(parent, index2);}public int find(int[] parent, int index) {if (parent[index] !&#61; index) {parent[index] &#61; find(parent, parent[index]);}return parent[index];}
}

4.2 针对有向图连通分量的求解

参考例子


推荐阅读
  • 本题探讨了在一个有向图中,如何根据特定规则将城市划分为若干个区域,使得每个区域内的城市之间能够相互到达,并且划分的区域数量最少。题目提供了时间限制和内存限制,要求在给定的城市和道路信息下,计算出最少需要划分的区域数量。 ... [详细]
  • 使用Vultr云服务器和Namesilo域名搭建个人网站
    本文详细介绍了如何通过Vultr云服务器和Namesilo域名搭建一个功能齐全的个人网站,包括购买、配置服务器以及绑定域名的具体步骤。文章还提供了详细的命令行操作指南,帮助读者顺利完成建站过程。 ... [详细]
  • 使用Python在SAE上开发新浪微博应用的初步探索
    最近重新审视了新浪云平台(SAE)提供的服务,发现其已支持Python开发。本文将详细介绍如何利用Django框架构建一个简单的新浪微博应用,并分享开发过程中的关键步骤。 ... [详细]
  • 本题涉及一棵由N个节点组成的树(共有N-1条边),初始时所有节点均为白色。题目要求处理两种操作:一是改变某个节点的颜色(从白变黑或从黑变白);二是查询从根节点到指定节点路径上的第一个黑色节点,若无则输出-1。 ... [详细]
  • 本题探讨如何通过最大流算法解决农场排水系统的设计问题。题目要求计算从水源点到汇合点的最大水流速率,使用经典的EK(Edmonds-Karp)和Dinic算法进行求解。 ... [详细]
  • 尽管深度学习带来了广泛的应用前景,其训练通常需要强大的计算资源。然而,并非所有开发者都能负担得起高性能服务器或专用硬件。本文探讨了如何在有限的硬件条件下(如ARM CPU)高效运行深度神经网络,特别是通过选择合适的工具和框架来加速模型推理。 ... [详细]
  • 给定行数 numRows,生成帕斯卡三角形的前 numRows 行。例如,当 numRows 为 5 时,返回的结果应为:[[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1]]。 ... [详细]
  • 本文介绍如何使用JPA Criteria API创建带有多个可选参数的动态查询方法。当某些参数为空时,这些参数不会影响最终查询结果。 ... [详细]
  • Codeforces Round #566 (Div. 2) A~F个人题解
    Dashboard-CodeforcesRound#566(Div.2)-CodeforcesA.FillingShapes题意:给你一个的表格,你 ... [详细]
  • 本题通过将每个矩形视为一个节点,根据其相对位置构建拓扑图,并利用深度优先搜索(DFS)或状态压缩动态规划(DP)求解最小涂色次数。本文详细解析了该问题的建模思路与算法实现。 ... [详细]
  • 本文介绍如何在Linux Mint系统上搭建Rust开发环境,包括安装IntelliJ IDEA、Rust工具链及必要的插件。通过详细步骤,帮助开发者快速上手。 ... [详细]
  • 作为一名专业的Web前端工程师,掌握HTML和CSS的命名规范是至关重要的。良好的命名习惯不仅有助于提高代码的可读性和维护性,还能促进团队协作。本文将详细介绍Web前端开发中常用的HTML和CSS命名规范,并提供实用的建议。 ... [详细]
  • 本文将介绍网易NEC CSS框架的规范及其在实际项目中的应用。通过详细解析其分类和命名规则,探讨如何编写高效、可维护的CSS代码,并分享一些实用的学习心得。 ... [详细]
  • FinOps 与 Serverless 的结合:破解云成本难题
    本文探讨了如何通过 FinOps 实践优化 Serverless 应用的成本管理,提出了首个 Serverless 函数总成本估计模型,并分享了多种有效的成本优化策略。 ... [详细]
  • C#设计模式学习笔记:观察者模式解析
    本文将探讨观察者模式的基本概念、应用场景及其在C#中的实现方法。通过借鉴《Head First Design Patterns》和维基百科等资源,详细介绍该模式的工作原理,并提供具体代码示例。 ... [详细]
author-avatar
zmhua123_681
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有