zoukankan      html  css  js  c++  java
  • 求两点之间所有路径的算法

    由于本篇博文的图不能正常显示,故将本篇博文的底稿上传。下载地址为:https://files.cnblogs.com/finallyliuyu/allpathbetweentwonodes.rar

    希望能对大家有用。另外需要指出的是:我的这个求两点之间所有路径的算法并不高效,但是可以保证正确,无论是有向图,还是无向图都可以使用。

    作者:finallyly 出处:技术(如若转载请注明作者和出处)

    最近在实现一个算法,算法之内有一个子算法是求有向图内两个定点(原点和目的点)之间的全部路径。在网上翻阅了大部分资料,发现给出的算法和代码要么只能解决DAG(有向无环图)的两定点之间所有路径问题,要么就是算法本身存在若干漏洞,连DAG图也无法解决。花费了一天的时间,自己写了个求简单有向图中(包括dag和非dag)两定点之间所有路径的算法,特共享出来。

    文章将按如下组织,首先给出path的定义,其次给出dag的定义,然后给出算法的伪代码,之后是算法的C++实现以及实验结果。

    1 Path的定义

    Path的定义是建立在walk,基础上的。参见Bondy的《Graph Theory With Applications》

    由上面的定义,我问可以得出path是一个结点和边交叠出现的序列,并且在这个序列中结点不能重复,边也不能重复。

    2 DAG的定义

    DAG(Directed Acyclic Graph):即不存在环路的有向图。或者说是DFS过程中不出现回边(backc edge)的图。如图2-1就是一个DAG。更一般的有向图见图2-2

    C0PT(L)6X@D71L}Y]3K(4C2

    2‑1 DAG

    ++++++++++++++++++++++++++++++++++++++

    第1条路径是:0-->1-->4-->11

    第2条路径是:0-->1-->3-->11

    第3条路径是:0-->1-->2-->6-->10-->11

    第4条路径是:0-->1-->2-->6-->9-->11

    第5条路径是:0-->1-->2-->5-->8-->11

    第6条路径是:0-->1-->2-->5-->7-->11

    ++++++++++++++++++++++++++++++++++++++

    }WK[LS69X1]O9Z`0CY[B{(2

    2‑2 Digraph

    该图对应的矩阵型存储格式为:

    Q5GPCJCK94}`}LVT6LQA@G5

    它的路径有:

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    第一条路径:0->1->2->3->4

    第二条路径:0->1->2->4

    第三条路径:0->1->3->2->4

    第四条路径:0->1->3->4

    第五条路径:0->1->4

    第六条路径:0->2->1->3->4

    第七条路径:0->2->1->4

    第八条路径:0->2->3->1->4

    第九条路径:0->2->3->4

    第十条路径:0->2->4

    第十一条路径:0->3->1->2->4

    第十二条路径:0->3->1->4

    第十三条路径:0->3->2->1->4

    第十四条路径:0->3->2->4

    第十五条路径:0->3->4

    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    3 算法设计

    待求解问题是“求原点和目的点之间的全部路径”,求解问题的第一步,我们需要确定这是一个P问题还是NP问题。对于P问题,可以直接设计算法;对于NP问题,则需要一些近似手段。值得庆幸的是这是一个P问题。算法最大复杂度为

    E_5P4C~D[8~U60H`_S)@U~E

    证明如下:

    假定有向图为N个节点的简单完全图,即每个节点都与其他N-1个节点有边相连。起始结点和结束节点确定,那么我们需要排列中间的N-2个节点,对于第一个非固定的节点,它有N-2种可能取值。。。以此类推得到上述答案。

    求两定点之间的全部路径,其根本是一个涉及到搜索和回溯的问题。我们设计算法时所关心的首要问题是:按照何种顺序搜索和回溯才能保证路径可以不重不漏地被全部找到。

    如下是算法设计部分

    图的存储结构:邻接矩阵。Arcs

    工作结构:结点栈 mystack;

    状态保存结构:

    (1) VertexStatus[]={0,0,0,1,1,…}。当结点未进栈或者已经出栈,则其对应的状态为0,否则状态为1;

    (2) ArcStatus[][]={0,0,1,0,1…..}当且仅当边的两个结点都在栈外时,边的状态才为0,否则为1。

    注意我们只所以设计如上结点、边两个状态存储结构,就是依据于path的定义,结点不重复,边不重复。具有边状态存储结构,也是我的算法与其他算法根本上的不同。

    不失一般性,我们假设原点的编号最小为0,目标点的编号最大N。我们的问题转换成了,求最小编号的节点与最大编号的节点之间的所有路径。

    Intial :

    Paths={}//路径集合

    VertexStatus[]={0};//全部置0

    ArcStatus[][]={0};////全部置0

    mystack.push(0);

    VertexStatus[0]=1;

    While(!mystack.empty())

    {

    Int elem= mystack.top();//获得栈顶元素

    if(elem==N)//找到了一条路径

    {

    path=Traverse(mystack);

    Paths.add(path);

    VertexStatus[elem]=0;

    UpdateArcStatus();//更新ArcStatus[][],使得所有两个端点都不在栈内的边的状态为0

    mystack.pop();//移除栈顶元素

    }

    else

    {

    i=0;

    For(;i<N;i++)

    { if(VertexStatus[i]=0&&ArcStatus[elem][i]=0&&Arcs.contain(elem,i))

    {

    VertexStatus[i]=1;

    ArcStatus[elem][i]=1;

    Mystack.push(i);//入栈

    break;

    }

    }

    if(i=N)//该节点没有符合要求的后续节点

    {

    VertexStatus[elem]=0;

    UpdateArcStaus();////更新ArcStatus[][],使得所有两个端点都不在栈内的边的状为0

    Mystack.pop();//出栈

    }

    }

    }

  • 相关阅读:
    Java.io.outputstream.PrintStream:打印流
    Codeforces 732F. Tourist Reform (Tarjan缩点)
    退役了
    POJ 3281 Dining (最大流)
    Light oj 1233
    Light oj 1125
    HDU 5521 Meeting (最短路)
    Light oj 1095
    Light oj 1044
    HDU 3549 Flow Problem (dinic模版 && isap模版)
  • 原文地址:https://www.cnblogs.com/finallyliuyu/p/2019534.html
Copyright © 2011-2022 走看看