• 某种带权有向无环图(graph)的所有路径的求法


    // 讨论QQ群:135202158

    最近做某个东西,最后用图实现了,这里总结一下算法。

    假设有以下带权有向无环图(连通或非连通,我这里用的是非连通的):

    每个节点(node)可能与其他节点有向地相连,相邻节点的边(edge)有权值(weight)属性。从一个节点到任意一个节点的连的集合称为路径(path),且路径的权为各边权的最小值。

    现在的问题就是求所有可能的路径,并算出各路径的权。

    以下是简单的C++代码实现,我是用遍历边来实现的,节点和边是两个数据结构:

      1 #include <iostream>
      2 #include <vector>
      3 #include <list>
      4 
      5 using namespace std;
      6 
      7 // 节点
      8 struct node
      9 {
     10     char val; 
     11 
     12     node(char c) : val(c) {}
     13 };
     14 
     15 //
     16 struct edge
     17 {
     18     // a->b,w为权
     19     node   a;
     20     node   b;
     21     int    w;
     22 
     23     edge(node& _a, node& _b, int _w) : a(_a), b(_b), w(_w) {}
     24 };
     25 
     26 // 遍历各边时所有的记录
     27 struct record
     28 {
     29     list<node>  path;   // 路径上的节点列表
     30     list<int>   ws;     // 当前的最小权列表
     31 };
     32 
     33 // 生成上图所示带权有向无环图
     34 void gen_samples(vector<node>& nodes, vector<edge>& edges);
     35 
     36 
     37 // 递归遍历
     38 void travel_path(vector<edge>& edges, edge& x, record& r)
     39 {
     40     size_t i;
     41     for(i=0; i<edges.size(); ++i)
     42     {
     43         edge e = edges[i];
     44         // 判断是否连通
     45         if(x.b.val == edges[i].a.val)
     46         {
     47             r.path.push_back(edges[i].b);
     48             int w = min(x.w, edges[i].w);
     49             r.ws.push_back(w);
     50             travel_path(edges, edges[i], r);
     51         }
     52     }
     53 
     54     // 不与任何节点有向连通,输出路径,并回溯至上个节点
     55     if(i == edges.size())
     56     {
     57         for(list<node>::iterator it = r.path.begin();
     58             it != r.path.end(); ++it)
     59             cout << it->val << " ";
     60         cout << ", " << r.ws.back() << endl;
     61 
     62         r.path.pop_back();
     63         r.ws.pop_back();
     64     }
     65 }
     66 
     67 
     68 int main()
     69 {
     70     vector<node> nodes;
     71     vector<edge> edges;
     72 
     73     gen_samples(nodes, edges);
     74 
     75     for(size_t i=0; i<edges.size(); ++i)
     76     {
     77         record r;
     78         r.path.push_back(edges[i].a);
     79         r.path.push_back(edges[i].b);
     80         r.ws.push_back(edges[i].w);
     81         
     82         travel_path(edges, edges[i], r);
     83     }
     84 
     85     system("PAUSE");
     86     return 0;
     87 }
     88 
     89 
     90 
     91 void gen_samples(vector<node>& nodes, vector<edge>& edges)
     92 {
     93     node a('A');    nodes.push_back(a);
     94     node b('B');    nodes.push_back(b);
     95     node c('C');    nodes.push_back(c);
     96     node d('D');    nodes.push_back(d);
     97     node e('E');    nodes.push_back(e);
     98     node f('F');    nodes.push_back(f);
     99     node g('G');    nodes.push_back(g);
    100     node h('H');    nodes.push_back(h);
    101     node i('I');    nodes.push_back(i);
    102     node j('J');    nodes.push_back(j);
    103     node k('K');    nodes.push_back(k);
    104 
    105     edge e1(a, c, 5);     edges.push_back(e1);
    106     edge e2(b, d, 2);     edges.push_back(e2);
    107     edge e3(b, e, 7);     edges.push_back(e3);
    108     edge e4(c, f, 4);     edges.push_back(e4);
    109     edge e5(c, h, 1);     edges.push_back(e5);
    110     edge e6(e, h, 5);     edges.push_back(e6);
    111     edge e7(g, i, 2);     edges.push_back(e7);
    112     edge e8(g, j, 8);     edges.push_back(e8);
    113     edge e9(h, k, 3);     edges.push_back(e9);
    114 }


    执行结果为(逗号前面是沿路径的各节点,后面的数字是路径的权):

    A C F , 4
    A C H K , 1
    A C H , 1
    A C , 5
    B D , 2
    B E H K , 3
    B E H , 5
    B E , 7
    C F , 4
    C H K , 1
    C H , 1
    E H K , 3
    E H , 5
    G I , 2
    G J , 8
    H K , 3


    出来的结果是所有可能的路径,如果要找包含某节点的最长路径的话,这个是有冗余的,需要去一下。

  • 相关阅读:
    Python 进阶_OOP 面向对象编程_实例属性和方法
    Python 进阶_OOP 面向对象编程_实例属性和方法
    Python 进阶_OOP 面向对象编程_类属性和方法
    Python 进阶_OOP 面向对象编程_类属性和方法
    Python 进阶_OOP 面向对象编程_类属性和方法
    Python 进阶_OOP 面向对象编程_类和继承
    pytest十四:doctest 框架
    pytest十三:配置文件 pytest.ini
    pytest十二:cmd命令行参数
    pytest十一:函数传参和 firture 传参数 request
  • 原文地址:https://www.cnblogs.com/zzqcn/p/3204112.html
Copyright © 2020-2023  润新知