給定乙個無向圖,如果它的某個子圖中任意兩個頂點都互相連通並且是一棵樹,那麼這棵樹就叫生成樹。如果邊上有權值,那麼使得邊權和最小的生成樹叫做最小生成樹(mst,minimum spanning tree)
比如讓你為乙個鎮的九個村莊架設通訊網路,每個村莊相當於乙個頂點,權值是村與村之間可通達的直線距離,要求你必須用最小的成本完成這次任務;或者
村莊之間建公路,連通n個村莊要n-1條路,如何讓建路成本最低之類的問題。
①該演算法是構建最小生成樹的演算法之一。它是以某頂點為起點,不斷新增各頂點上最小權值的邊,來構建最小生成樹。
②演算法流程:
第一步:設圖g頂點集合為u,首先任意選擇圖g中的一點作為起始點a,將該點加入集合v;
第二步:從集合u中找到另一點b使得點b到v中任意一點的權值最小,此時將b點也加入集合v;
以此類推,現在的集合v=,再從集合u中找到另一點c使得點c到v中任意一點的權值最小,此時將c點加入集合v;直至所有頂點全部被加入v,此時就構建出了一棵mst。
#include #include摘自#define int_max 1000000000
using
namespace
std;
int matrix[100][100];//
鄰接矩陣
bool visited[100];//
標記陣列
int path[100];//
記錄生成樹路徑
int lowcost[100];//
邊的權值
int vertex_num,arc_num;//
頂點數,弧數
int sum;//
權值總和
int source;//
源點void prim(int
source);
intmain()
cout
<< "
請輸入起點(<
"<< vertex_num << "):"
; cin >>source;
prim(source);
cout
<< "
最小生成樹權和為:
"<< sum <
cout
<< "
最小生成樹路徑為:\n";
for (int i = 0; i < vertex_num; i++)
if (i !=source)
cout
<< i << "
----
"<< path[i] <
return0;
}void prim(int
source)
int min_cost,min_cost_index;//
最小的權值,和其下標
sum=0
;
for(int i=1;i//
找除源點外的n-1個點,如果這裡寫多了,
//那麼下邊的for裡if進不去,那麼sum的值也會錯誤
min_cost=int_max;
for(int j=0;j//
遍歷所有頂點
if(visited[j]==false&&lowcost[j]//
找到與源點的權值最小的點
min_cost=lowcost[j];
min_cost_index=j;}}
visited[min_cost_index]=true;//
講找到的頂點進行標記
sum+=min_cost;//
權值總和
for(int j=0;j)}}
}
①該演算法是構建最小生成樹的另乙個演算法,其是對邊進行操作,來構建最小生成樹的。
②演算法流程:
第一步:把所有的邊按權值從小到大排列。
第二步:按照順序選取每條邊,如果這條邊的兩個端點不屬於同一集合,那麼就將它們合併。
重複第二步,直到 所有的點都屬於同乙個集合。
第二步用並查集來實現,又因為每次都選的權值最小的,所以這其實就是運用並查集的貪心演算法。
③為什麼這樣做就可以構建最小生成樹呢?因為n個頂點只需要n-1條邊就夠了,那麼選哪n-1條呢,為了讓權值和最小,當然選從小到大排序的前n-1條邊嘍。
#include #includeprim演算法時間複雜度為#define max_int 100
using
namespace
std;
struct edgeedge[max_int];
int par[max_int];//
i的父親的編號
int rank[max_int];//
i的高度
int vertex_num,arc_num;//
頂點數,弧數
int case_num;//
測試組數
int sum;//
權值總和
void init(int n);//
初始化int find(int x);//
查詢根節點並且壓縮路徑
bool unite(int x,int y);//
合併bool compare(const edge&a,const edge&b);
intmain()
sort(edge,edge+arc_num,compare);
cout
<
最小生成樹的路徑為:
"<
intj;
for(j=0;j)
}if(j==arc_num)
else
if(j
case_num--;
}return0;
}void init(intn)}
int find(int
x)else
}bool unite(int x,int
y)else
else
return
true
; }
}bool compare(const edge&a,const edge&b)
,與網中的邊數無關,適用於求邊稠密的網的最小生成樹。
kruskal演算法時間複雜度為
,適用於求稀疏的網的最小生成樹。
最小生成樹(prim演算法)
最小生成樹是資料結構中圖的一種重要應用,它的要求是從乙個帶權無向完全圖中選擇n 1條邊並使這個圖仍然連通 也即得到了一棵生成樹 同時還要考慮使樹的權最小。prim演算法要點 設圖g v,e 其生成樹的頂點集合為u。把v0放入u。在所有u u,v v u的邊 u,v e中找一條最小權值的邊,加入生成樹...
最小生成樹 Prim演算法
prim 演算法 以領接矩陣儲存 圖g bool b i 表示頂點i是否被訪問,初始化時候memset b,false,sizeof b b 0 value,表示從第0個節點開始。用value i 表示節點i到最小生成樹a中定點的最小距離。例如value 1 a 0 1 int sum記錄權值和 i...
最小生成樹 prim 演算法
一 演算法描述 假設存在連通帶權圖g v,e 其中最小生成樹為t,首先從圖中隨意選擇一點s屬於v作為起始點,並將其標記後加入集合u 中。然後演算法重複執行操作為在所有v屬於u,u屬於v u的邊 v0,u0 屬於e中找一條代價最小的邊並加入集合t,同時將u0併入u,直到u v為止。這是,t中必有n 1...