1. 程式人生 > >對於prim的一個有趣但有點奇怪的想法

對於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,並不是屬於初始頂點到各個頂點的權重值,但它初始記錄這些值,在之後的更新中一直來記錄最小權值。 */