Johnson算法寻找图中的所有简单环路

2024-01-27 01:08

本文主要是介绍Johnson算法寻找图中的所有简单环路,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Johnson算法论文:https://www.cs.tufts.edu/comp/150GA/homeworks/hw1/Johnson%2075.PDF

Johnson算法讲解视频:https://www.youtube.com/watch?v=johyrWospv0

一篇解释原理较好的博客:https://blog.csdn.net/Azeroit/article/details/105401120?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase

C++实现代码:

#include <iostream>
#include<vector>
#include<map>
#include<cstring>
using namespace std;//using johnson algorithm
int visited[10010],dfn[10010],low[10010],ins[10010],stack[10010],color[10010],top=0,cnt,N,M,stamp=0;
vector<int> V[10010],VC[10010];
vector<int> scc[10010];map<int,vector<int>> blockedmap;  //stack,ins 可以重复利用,ins充当blockedset的作用 先用vector,不对就换set
vector<vector<int>> ans;  //存放结果
void tarjan(int u){dfn[u]=low[u]=++stamp;stack[++top]=u;ins[u]=1;for(int i=0;i<V[u].size();i++){int v=V[u][i];if(!dfn[v]){tarjan(v);low[u]=min(low[u],low[v]);}else if(ins[v])low[u]=min(low[u],dfn[v]);}if(dfn[u]==low[u]){cnt++; int y;do {y = stack[top--], ins[y] = 0;/*c[y] = cnt, */color[y] = cnt,scc[cnt].push_back(y);} while (u!= y);}
}void stronglycomponent(){for(int i=1;i<=N;i++){if(!dfn[i]) tarjan(i);}
}void unlock(int u){ins[u]=0;if(!blockedmap[u].empty()){for(auto e:blockedmap[u]){if(ins[e]) unlock(e);}}blockedmap[u].clear();
}
bool Findcycles(int start,int cur){//printf("f(%d,%d)\n",start,cur);bool f=false;// 是否找到环stack[++top]=cur;ins[cur]=1;for(auto e:VC[cur]){if(!visited[e]){if(e==start){//保存结果vector<int> path;for(int i=1;i<=top;i++)path.push_back(stack[i]);ans.push_back(path);f=true;}else if(!ins[e]){//bool flag=Findcycles(start,e);  //不能合并写f=(Findcycles(start,e))||f;  //次序不能颠倒}}}if(f) unlock(cur);else{for(auto e:VC[cur]){if(!visited[e]) blockedmap[e].push_back(cur);}}--top;return f;
}
int main()
{cin>>N>>M;//默认编号0-N-1for(int i=0;i<M;i++){int a,b;cin>>a>>b;V[a].push_back(b);}stronglycomponent();//显示强连通分量printf("显示强连通分量\n");cout<<"cnt is "<<cnt<<endl;for(int i=1;i<=cnt;i++){for(int j=0;j<scc[i].size();j++){printf("%d ",scc[i][j]);}printf("\n");}//缩点for(int i=1;i<=N;i++){for(int j=0;j<V[i].size();j++){if(color[i]==color[V[i][j]]){VC[i].push_back(V[i][j]);}}}//寻找所有简单回路memset(ins,0,sizeof(ins));for(int startindex=1;startindex<=N;startindex++){Findcycles(startindex,startindex);visited[startindex]=1;}//显示结果printf("显示结果\n");for(int i=0;i<ans.size();i++){for(int j=0;j<ans[i].size();j++){printf("%d ",ans[i][j]);}printf("\n");}
}

以视频中的输入例子为测试:

输入:

9 15
1 2
1 5
1 8
2 3
2 7
2 9
3 1
3 2
3 4
3 6
4 5
5 2
6 4
8 9
9 8

输出:

1 2 3
1 5 2 3
2 3
2 3 4 5
2 3 6 4 5
8 9

 

这篇关于Johnson算法寻找图中的所有简单环路的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/648613

相关文章

openCV中KNN算法的实现

《openCV中KNN算法的实现》KNN算法是一种简单且常用的分类算法,本文主要介绍了openCV中KNN算法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录KNN算法流程使用OpenCV实现KNNOpenCV 是一个开源的跨平台计算机视觉库,它提供了各

MySQL中动态生成SQL语句去掉所有字段的空格的操作方法

《MySQL中动态生成SQL语句去掉所有字段的空格的操作方法》在数据库管理过程中,我们常常会遇到需要对表中字段进行清洗和整理的情况,本文将详细介绍如何在MySQL中动态生成SQL语句来去掉所有字段的空... 目录在mysql中动态生成SQL语句去掉所有字段的空格准备工作原理分析动态生成SQL语句在MySQL

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

使用Python开发一个简单的本地图片服务器

《使用Python开发一个简单的本地图片服务器》本文介绍了如何结合wxPython构建的图形用户界面GUI和Python内建的Web服务器功能,在本地网络中搭建一个私人的,即开即用的网页相册,文中的示... 目录项目目标核心技术栈代码深度解析完整代码工作流程主要功能与优势潜在改进与思考运行结果总结你是否曾经

Mysql表的简单操作(基本技能)

《Mysql表的简单操作(基本技能)》在数据库中,表的操作主要包括表的创建、查看、修改、删除等,了解如何操作这些表是数据库管理和开发的基本技能,本文给大家介绍Mysql表的简单操作,感兴趣的朋友一起看... 目录3.1 创建表 3.2 查看表结构3.3 修改表3.4 实践案例:修改表在数据库中,表的操作主要

springboot简单集成Security配置的教程

《springboot简单集成Security配置的教程》:本文主要介绍springboot简单集成Security配置的教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录集成Security安全框架引入依赖编写配置类WebSecurityConfig(自定义资源权限规则

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

Python实现将MySQL中所有表的数据都导出为CSV文件并压缩

《Python实现将MySQL中所有表的数据都导出为CSV文件并压缩》这篇文章主要为大家详细介绍了如何使用Python将MySQL数据库中所有表的数据都导出为CSV文件到一个目录,并压缩为zip文件到... python将mysql数据库中所有表的数据都导出为CSV文件到一个目录,并压缩为zip文件到另一个

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件