zoukankan      html  css  js  c++  java
  • 对于prim的一个有趣但有点奇怪的想法

    prim算法找最小生成树适用于无向图,对于有向加权图会产生错误。

    比如

    1->2,8

    1->3,8

    2->3,4

    3->2,3

    最小生成树1->2->3

    而不是3->2;

    这是因为2,3之间相互的边在prim算法中无法判断,或者根本意识不到3->2这条边。

    我突然想到如果在判断2的最小边时将以2为入度的边的也加入判断,这样就可以遍历到3-》2边,但这样又会产生一个问题,记录下的边是2->3 ,3。

    这样就相当于记录了一条方向相反的边,这条边是不存在的。但我们可以在记录这样的边时做个标记,在存储这种边时在进行改正。但这样有些麻烦,不如再写一个KrusKal.

    (其实我是偷懒,写prim时生成的图是有向图,但实在不想改太多,所以想了这么个办法来解决,但这个想法好像可以让prim来检测有向图,插一段代码,标记部分没写,如果有错误的地方或者不合适的注释,还请各位指出,鄙人不胜感激)

    参考:https://www.cnblogs.com/ShiveryMoon/p/7859360.html

    edge* Graph::prim(int cur) {
        if (cur >= this->vertexNum) {
            return NULL;
        }
        int *weight = new int[this->vertexNum];
        this->minPath = new edge[this->vertexNum - 1];//存储最小生成树的边
        int *neighbor = new int[this->vertexNum];//记录与i点距离最近的顶点的编号,应该是找到该节点的前驱节点标记
        bool* U = new bool[this->vertexNum];//已加入最小生成树的节点,规定节点在该数组中为true;不在为fasle
        for (int i = 0; i < this->vertexNum; i++){
            U[i] = false;
        }
        U[cur] = true;
        for (int i = 0; i < this->vertexNum; i++) {
            weight[i] = this->matrix[cur][i];//记录第一个节点与其他节点的权值
            neighbor[i] = cur;
        }
        int index;//记录最小权值边所连接的顶点
        neighbor[cur] = -1;//
        for (int i = 1; i < this->vertexNum; i++) {//i表示寻找边的次数,有n个节点,则寻找n-1次,i不参与任何邻接矩阵的寻值
            int min = INFINIT;
            for (int j = 0; j < this->vertexNum; j++) {
                if (min > weight[j] && U[j] == false) {
                    index = j;
                    min = weight[j];
                }
            }
            U[index] = true;
            if (neighbor[index] >= 0) {
                minPath[i-1].setValue(neighbor[index], index, min);
                /*temp[i].setStartVertex(neighbor[index]);
                temp[i].setEndVertex(index);
                temp[i].setWeight(min);*/
                //不知道为什么始无法通过上述句子给temp[i]赋值,先注释掉
                cout << neighbor[index] << ' ' << index<<' ' << min << endl;
            }
            for (int j = 0; j < this->vertexNum; j++) {
                if (weight[j] > this->matrix[index][j]||weight[j]>this->matrix[j][index] && U[j] == false) {
                    neighbor[j] = index;
                    weight[j] = this->matrix[index][j] > this->matrix[j][index] ? this->matrix[j][index]: this->matrix[index][j];
                }
            }
        }
        return this->minPath;
    }
    /*prim:
        neighbor记录的是寻找到每个节点的前驱节点。如果在第二个for循环里没有找到以第二个为线索的后继节点,则下一个找到的节点必然以第一个
        节点为线索。(初始顶点已知,第一个for循环以初始顶点为线索找到第二个顶点,第二个for循环则以第二个顶点为线索,寻找是否有符合条件的第三个
        顶点,如果有,将第三个顶点的前驱(线索)记录到neighbor中,同时跟新权重(weight)值,使得下一次寻找时能够找到第三个顶点。
        关于weight,并不是属于初始顶点到各个顶点的权重值,但它初始记录这些值,在之后的更新中一直来记录最小权值。
    */
  • 相关阅读:
    if 语句
    变量命名
    python变量
    运算符
    注释
    PyCharm
    python版本,执行
    Tornado 【简述】
    Git 【管理篇】
    MySQL的介绍
  • 原文地址:https://www.cnblogs.com/yuxi-blog/p/10116594.html
Copyright © 2011-2022 走看看