当前位置: 首页 > 知识库问答 >
问题:

无向强连通图的所有单路

潘凯
2023-03-14
void Graph::printAllPaths(int s, int d)
{
    // Mark all the vertices as not visited
    bool *visited = new bool[V];

    // Create an array to store paths
    int *path = new int[V];
    int path_index = 0; // Initialize path[] as empty

    // Initialize all vertices as not visited
    for (int i = 0; i < V; i++)
        visited[i] = false;

    // Call the recursive helper function to print all paths
    printAllPathsUtil(s, d, visited, path, path_index);
}

// A recursive function to print all paths from 'u' to 'd'.
// visited[] keeps track of vertices in current path.
// path[] stores actual vertices and path_index is current
// index in path[]
void Graph::printAllPathsUtil(int u, int d, bool visited[],
                          int path[], int &path_index)
{
    // Mark the current node and store it in path[]
    visited[u] = true;
    path[path_index] = u;
    path_index++;

    // If current vertex is same as destination, then print
    // current path[]
    if (u == d)
    {
        for (int i = 0; i<path_index; i++)
            cout << path[i] << " ";
        cout << endl;
    }
    else // If current vertex is not destination
    {
        // Recur for all the vertices adjacent to current vertex
        list<int>::iterator i;
        for (i = adj[u].begin(); i != adj[u].end(); ++i)
            if (!visited[*i])
                printAllPathsUtil(*i, d, visited, path, path_index);
    }

    // Remove current vertex from path[] and mark it as unvisited
    path_index--;
    visited[u] = false;
}

共有1个答案

盖博简
2023-03-14
void Graph::addEdge(int u, int v)
{
    adj[u].push_back(v); 
    adj[v].push_back(u); // Fix: add back edge as well!
}
#pragma once

#ifdef __cplusplus
extern "C" {  // only need to export C interface if
              // used by C++ source code
#endif

    typedef struct tagNodeListNode {
        struct tagNodeListNode* next;
        int index;
    } NodeListNode;

    typedef struct tagGraph {
        int nodesCount;
        NodeListNode** adjArr;
    } Graph;


    typedef void(*GraphPathVisitorFunc)(NodeListNode const* const path);

    Graph GraphCreate(int nodesCount);
    void GraphDestroy(Graph gr);
    void GraphAddEdge(Graph gr, int u, int v);
    void GraphVisitAllPaths(Graph gr, int s, int d, GraphPathVisitorFunc visitor);
    void GraphPrintAllPaths(Graph gr, int s, int d);


#ifdef __cplusplus
}
#endif
#include "Graph.h"

#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>


Graph GraphCreate(int nodesCount)
{
    // calloc ensures zeroing array
    NodeListNode** adjArr = (NodeListNode**)calloc(nodesCount, sizeof(NodeListNode*));
    Graph gr = { nodesCount, adjArr };
    return gr;
}

void GraphDestroy(Graph gr)
{
    for (int i = 0; i < gr.nodesCount; i++)
    {
        for (NodeListNode* adj = gr.adjArr[i]; adj != NULL;)
        {
            NodeListNode* tmp = adj;
            adj = adj->next; //first move on the free
            free(tmp);
        }
    }
    free(gr.adjArr);
}

void GraphAddEdgeImplFirst(Graph gr, int from, int to)
{
    NodeListNode* adj = gr.adjArr[from];
    NodeListNode* n = (NodeListNode*)malloc(sizeof(NodeListNode));
    n->next = adj;
    n->index = to;
    gr.adjArr[from] = n;
}

void GraphAddEdgeImplLast(Graph gr, int from, int to)
{
    NodeListNode* adj = gr.adjArr[from];
    NodeListNode* n = (NodeListNode*)malloc(sizeof(NodeListNode));
    n->next = NULL;
    n->index = to;
    if(adj == NULL)
    {
        gr.adjArr[from] = n;
    }
    else
    {
        while (adj->next != NULL)
            adj = adj->next;
        adj->next = n;
    }
}



void GraphAddEdge(Graph gr, int u, int v)
{
    GraphAddEdgeImplFirst(gr, u, v);
    GraphAddEdgeImplFirst(gr, v, u);

    // closer to https://ideone.com/u3WoIJ but slower and thus makes no sense
    //GraphAddEdgeImplLast(gr, u, v);
    //GraphAddEdgeImplLast(gr, v, u);
}


void GraphVisitAllPathsImpl(Graph gr, int cur, int dst, GraphPathVisitorFunc visitor, NodeListNode* pathFst, NodeListNode* pathLst, bool* visited)
{
    if (cur == dst)
    {
        visitor(pathFst);
        return;
    }

    NodeListNode* adj = gr.adjArr[cur];
    for (NodeListNode const* tmp = adj; tmp != NULL; tmp = tmp->next)
    {
        int next = tmp->index;
        if (visited[next])
            continue;
        visited[next] = true;
        NodeListNode nextNode = { NULL,next };
        pathLst->next = &nextNode;

        GraphVisitAllPathsImpl(gr, next, dst, visitor, pathFst, &nextNode, visited);

        pathLst->next = NULL;
        visited[next] = false;
    }
}

void GraphVisitAllPaths(Graph gr, int start, int dst, GraphPathVisitorFunc visitor)
{
    bool* visited = calloc(gr.nodesCount, sizeof(bool));
    visited[start] = true;
    NodeListNode node = { NULL,start };
    GraphVisitAllPathsImpl(gr, start, dst, visitor, &node, &node, visited);
    free(visited);
}


void PrintPath(NodeListNode const* const path)
{
    for (NodeListNode const* tmp = path; tmp != NULL; tmp = tmp->next)
    {
        printf("%d ", tmp->index);
    }
    printf("\n");
}

void GraphPrintAllPaths(Graph gr, int s, int d)
{
    GraphVisitAllPaths(gr, s, d, PrintPath);
}
void testGraph()
{
    Graph gr = GraphCreate(20);

    GraphAddEdge(gr, 0, 1);
    GraphAddEdge(gr, 0, 7);

    GraphAddEdge(gr, 1, 2);
    GraphAddEdge(gr, 1, 6);
    GraphAddEdge(gr, 1, 5);

    GraphAddEdge(gr, 2, 3);
    GraphAddEdge(gr, 2, 5);

    GraphAddEdge(gr, 3, 4);
    GraphAddEdge(gr, 3, 5);

    GraphAddEdge(gr, 4, 5);
    GraphAddEdge(gr, 4, 10);
    GraphAddEdge(gr, 4, 11);

    GraphAddEdge(gr, 5, 6);
    GraphAddEdge(gr, 5, 10);
    GraphAddEdge(gr, 5, 11);

    GraphAddEdge(gr, 6, 7);
    GraphAddEdge(gr, 6, 8);
    GraphAddEdge(gr, 6, 9);
    GraphAddEdge(gr, 6, 10);

    GraphAddEdge(gr, 7, 8);

    GraphAddEdge(gr, 8, 9);
    GraphAddEdge(gr, 8, 13);

    GraphAddEdge(gr, 9, 10);
    GraphAddEdge(gr, 9, 13);
    GraphAddEdge(gr, 9, 12);

    GraphAddEdge(gr, 10, 12);

    GraphAddEdge(gr, 11, 12);

    GraphAddEdge(gr, 12, 13);
    GraphAddEdge(gr, 12, 14);
    GraphAddEdge(gr, 12, 16);

    GraphAddEdge(gr, 13, 14);

    GraphAddEdge(gr, 14, 15);

    GraphAddEdge(gr, 16, 17);

    GraphAddEdge(gr, 15, 17);
    GraphAddEdge(gr, 15, 19);

    GraphAddEdge(gr, 17, 18);
    GraphAddEdge(gr, 17, 19);

    GraphAddEdge(gr, 18, 19);

    GraphPrintAllPaths(gr, 12, 4);

    GraphDestroy(gr);
}
 类似资料:
  • 根据CLRS第3版的定义,单连通有向图是指每对顶点(u,v)至多有一条唯一的路从u->v来的图。现在我读过的大多数答案都说,我们从图中的每个顶点运行DFS,如果在任何情况下我们找到一条交叉边或一条前向边,那么图就不是单连通的。我可以理解前向边的概念,但是在这个图上运行这个algo 1-->2<--3将给出一个结果:它不是单连通的,而这个图是单连通的。我们有一个从3->2或1->2的交叉边,这取决于

  • 考虑一个不连通的有向图的例子,其中顶点和边其中顶点是孤立的。 根据这里的答案:(对强连通图的最小加法),保证这个图所需的最小边数结果是3。 如何找到将这些边添加到哪里,即图中一条边的起始点和终止点?

  • 我想在无向图中找到一个强连通分量,即如果我从一个节点开始,那么我将回到节点,并且每个边都被精确地访问一次。 对于有向图,可以用Tarjan算法求强连通分量,但是对于无向图,该怎么办。

  • 给定一个一般的无向图,如何在O(n+m)时间内打印出图的所有双连通分量?我知道Tarjan的算法,用于输出无向图的所有连接点,但我发现很难扩展该算法来打印双连接的组件。我试着搜索google,但我得到的所有结果都不能用于我的测试用例,因为它们错过了算法的边缘情况。 编辑:我已经成功地实现了Niklas提供的这个链接中描述的算法。现在我有一个不同的问题,我如何找出一个不含边的无向图的子图,如果删除它

  • 设,一个无向连通图,完全没有桥。描述了一种引导边的算法,使得新图是一个SCC。 我建议的算法 所以我们从任意顶点运行DFS。我们注意到,由于它是一个无向图,所以只有树边和后边(对吗?)。我们相应地连接边(一个树边将被引导为“向下”,一个后边将被引导为“向上”)。 谢谢

  • 我有一个强连通图。我想移除一个边并检查是否仍然保持强连接。因为我将N=图中节点的总数取为10,并且我感兴趣的大多数图都有25条以上的边,所以很难检查一次使用一条,去掉边。 如何解决这个问题?多谢了。