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