在图中找到一个简单循环并打印它的算法

Posted

技术标签:

【中文标题】在图中找到一个简单循环并打印它的算法【英文标题】:Algorithm that finds a simple cycle in the graph and prints it 【发布时间】:2021-12-20 02:58:04 【问题描述】:

令 G=(V,E) 是一个简单的无向图。建议一种算法,在图中找到一些简单的循环并将其打印出来(组成它的节点序列)。如果没有这样的循环,算法将不会打印任何内容。


算法:

    初始化一个大小为 n 的数组,并为每个顶点创建一个父变量。 在随机顶点上启动 DFS,并为每个访问的顶点在数组中标记“1”,并分配其父节点。 如果在 DFS 运行中,下一个顶点是已标记的顶点,但不是其父节点 - 图中存在一个循环,并使用其父变量向后打印所有节点。

算法正确吗?还是我需要改变一些东西?

谢谢!

【问题讨论】:

我觉得不错。 @DavidEisenstat 谢谢! 我要补充一点,您需要跟踪“已访问”顶点的计数。如果 DFS 没有找到循环,但不是所有的顶点都被访问过,这意味着该图没有连接,您需要从任何其他未访问的顶点开始另一个 DFS。 【参考方案1】:

从图论我们知道:

    如果图的顶点数多于边数,则不存在环(闭合轮廓)。 如果图的顶点数等于边数,则图只有一个环。 如果图的顶点数少于边数,则图有多个闭合轮廓。

我提供算法深度优先搜索,它在图中找到一个简单的循环并打印出来:

#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
const int maximumSize=40;
vector<vector<int>> visited(maximumSize, vector<int>(maximumSize, 0));
vector<int> graph[maximumSize], closedContour, temporary;
int vertices, edges;
set<vector<int>> contours;
void showContentSetVector(set<vector<int>> input)

    for(auto iterator=input.begin(); iterator!=input.end(); ++iterator)
    
        for(auto item : *iterator)
        
            cout<<item<<", ";
        
        cout<<endl;
    
    return;

bool compare(int i,int j)

    return (i<j);

void createGraph()

    cin>>vertices>>edges;
    int vertex0, vertex1;
    for(int i=1; i<=edges; ++i)
    
        cin>>vertex0>>vertex1;
        graph[vertex0].push_back(vertex1);
        graph[vertex1].push_back(vertex0);
    
    return;

void depthFirstSearch(int initial, int current, int previous)

    if(visited[initial][current]==1)
    
        for(int i=0; i<temporary.size(); ++i)
        
            if(temporary[i]==current)
            
                for(int j=i; j<temporary.size(); ++j)
                
                    closedContour.push_back(temporary[j]);
                
            
        
        sort(closedContour.begin(), closedContour.end(), compare);
        contours.insert(closedContour);
        closedContour.clear();
        return;
    
    visited[initial][current]=1;
    temporary.push_back(current);
    for(int next : graph[current])
    
        if(next==previous)
        
            continue;
        
        depthFirstSearch(initial, next, current);
    
    temporary.pop_back();
    return;

void solve()

    createGraph();
    for(int vertex=1; vertex<=vertices; ++vertex)
    
        temporary.clear();
        depthFirstSearch(vertex, vertex, -1);
    
    cout<<"contours <- ";
    showContentSetVector(contours);
    return;

int main()

    solve();
    return 0;

结果如下:

contours <- 
1, 2, 3, 4, 
6, 7, 8, 

【讨论】:

以上是关于在图中找到一个简单循环并打印它的算法的主要内容,如果未能解决你的问题,请参考以下文章

特定类型图中的最长路径

高中简单信息编程问题?

Java排序算法:简单选择排序

插入排序算法解析

适用于负循环的 Floyd-Warshall 算法 [关闭]

L6-2 嵌套循环