連通分量是指圖的乙個子圖,子圖中任意兩個頂點之間都是可達的。最小生成樹是連通圖的乙個連通分量,且所有邊的權值和最小。
最小生成樹中,乙個頂點最多與兩個頂點鄰接;若連通圖有n個頂點,則最小生成樹中一定有n-1條邊。
prim演算法需要兩個線性表來進行輔助:
標記已經加入生成樹的頂點;(它的功能可以由tree取代)
初始狀態:生成樹根節點為真,其它為0。
記錄生成樹,tree[x]儲存頂點x的直接根節點下標,若x為樹的根節點則tree[x]為其自身。
初始狀態:根節點為其自身,其它頂點為null。
low[i]記錄生成樹中頂點與生成樹外頂點i所有邊中的最小值。
初始狀態:生成樹根節點與其它邊之間的權值。
prim演算法採用貪心的思想進行設計:
(1) 初始化:將起始點加入生成樹中
(2) 在生成樹中的頂點與其它頂點之間的邊中尋找最小的邊加入生成樹中(更新visited,tree);
(3) 搜尋新加入頂點與所有生成樹外頂點i之間邊,若小於原有low[i]則更新low[i];
(4) 重複執行,直至生成樹中包含了所有頂點。
prim演算法與dijsktra演算法非常類似,兩者在執行過程上的顯著區別在於:prim演算法按邊進行搜尋,將最小邊加入生成樹中;
dijsktra演算法按頂點進行搜尋,選擇樹外頂點與源點之間最短的邊(路徑)加入生成樹中。
【你如果非手算不可的話】記得在加入新頂點時,標記已加入到生成樹中的邊以及生成樹頂點之間的邊。
#define n 10000
int map[n][n],low[n],visited[n],tree[n];
int m, n;
int prim()//以0作為起點(生成樹的根)
}tree[0] = 0;//
//get mini
for(i = 0; i < n - 1; i++)
}tree[pos] = i;
result += min;
visited[pos] = 1;
//update low
for(j = 0; j < n; j++) }}
return result; //返回總代價
}
kruskal演算法的步驟:
1.對所有邊進行從小到大的排序。
2.每次選一條邊(最小的邊),如果如果形成環,就不加入(u,v)中,否則加入。那麼加入的(u,v)一定是最佳的。
【如果你非手算不可的話】從小到大地搜尋所有邊,若不產生環則加入生成樹中。kruskal演算法是手動求最小生成樹的不錯選擇。
採用遞迴的方式判斷環的存在:
int find(int x) //find the root
else
}
parent[x]儲存頂點x的直接根節點下標,若x為樹的根節點則parent[x]為其自身。find函式可以求出節點x的根節點,從而判斷是否有環形成。
int head[n],tail[n],weight[n];
int parent[n],sorted[n];
int cmp(const void *ip, const void *jp)
int find(int x) //find the root
else
}//m vertex, n edge
int kruskal()
for(i=0; i < n; i++)
//sort(r,r+m,cmp);
qsort(sorted, m, sizeof(int), cmp);
for(i = 0; i < m; i++)
}if (count < n - 1)
return ans;
}
最小生成樹 Prim演算法和Kruskal演算法
最小生成樹 3條構造最小生成樹的準則 只能使用該網路中的邊來構造最小生成樹 只能使用恰好n 1條邊來聯結網路中的n個結點 選用的這個n 1條邊不能構成迴路。mst性質 假設n v,是乙個連通網,u是頂點集合v的乙個非空子集。若 u,v 是一條具有最小值 代價 的邊,其中u屬於u,v屬於v u 即u對...
最小生成樹 Prim演算法和Kruskal演算法
轉於 prim演算法 設圖g v,e 其生成樹的頂點集合為u。把v0放入u。在所有u u,v v u的邊 u,v e中找一條最小權值的邊,加入生成樹。把 找到的邊的v加入u集合。如果u集合已有n個元素,則結束,否則繼續執行 其演算法的時間複雜度為o n 2 define maxn boolflag ...
最小生成樹 Prim演算法和Kruskal演算法
prim演算法 演算法簡單描述 1 輸入 乙個加權連通圖,其中頂點集合為v,邊集合為e 2 初始化 vnew 其中x為集合v中的任一節點 起始點 enew 為空 3 重複下列操作,直到vnew v a.在集合e中選取權值最小的邊,其中u為集合vnew中的元素,而v不在vnew集合當中,並且v v 如...