对于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,并不是属于初始顶点到各个顶点的权重值,但它初始记录这些值,在之后的更新中一直来记录最小权值。
*/

猜你喜欢

转载自www.cnblogs.com/yuxi-blog/p/10116594.html