設g = (v,e)是無向連通帶權圖,即乙個網路。e中的每一條邊(v,w)的權為c[v][w]。如果g的子圖g』是一棵包含g的所有頂點的樹,則稱g』為g的生成樹。生成樹上各邊權的總和稱為生成樹的耗費。在g的所有生成樹中,耗費最小的生成樹稱為g的最小生成樹。構造最小生成樹的兩種方法:prim演算法和kruskal演算法。
設g = (v,e)是連通帶權圖,u是v的真子集。如果(u,v)∈e,且u∈u,v∈v-u,且在所有這樣的邊中,(u,v)的權c[u][v]最小,那麼一定存在g的一棵最小生成樹,它意(u,v)為其中一條邊。這個性質有時也稱為mst性質。
設g = (v,e)是連通帶權圖,v = 。構造g的最小生成樹prim演算法的基本思想是:首先置s = ,然後,只要s是v的真子集,就進行如下的貪心選擇:選取滿足條件i ∈s,j ∈v – s,且c[i][j]最小的邊,將頂點j新增到s中。這個過程一直進行到s = v時為止。在這個過程中選取到的所有邊恰好構成g的一棵最小生成樹。
如下帶權圖:
生成過程:
1 -> 3 : 1
3 -> 6 : 4
6 -> 4: 2
3 -> 2 : 5
2 -> 5 : 3
實現:
#include #include #include using namespace std ;
struct treenode
public:
int m_nvertexindexa ;
int m_nvertexindexb ;
int m_nweight ;
} ;class mst_prim
void doprim ()
for (int j = 0; j < m_nnodecount; ++ j)
}++ i ;
}bflag[nmaxindexb] = true ;
m_tnmstree.push_back (treenode(nmaxindexa, nmaxindexb, nmaxweight)) ;
++ j ;
}// 輸出結果
for (vector::const_iterator ite = m_tnmstree.begin() ;
ite != m_tnmstree.end() ;
++ ite )
}private:
vector> m_nvgraph ; // 無向連通圖
vectorm_tnmstree ; // 最小生成樹
int m_nnodecount ;
} ;int main()
graph[0][1]= 6 ;
graph[0][2] = 1 ;
graph[0][3] = 5 ;
graph[1][2] = 5 ;
graph[1][4] = 3 ;
graph[2][3] = 5 ;
graph[2][4] = 6 ;
graph[2][5] = 4 ;
graph[3][5] = 2 ;
graph[4][5] = 6 ;
graph[1][0]= 6 ;
graph[2][0] = 1 ;
graph[3][0] = 5 ;
graph[2][1] = 5 ;
graph[4][1] = 3 ;
graph[3][2] = 5 ;
graph[4][2] = 6 ;
graph[5][2] = 4 ;
graph[5][3] = 2 ;
graph[5][4] = 6 ;
mst_prim mstp (graph) ;
mstp.doprim () ;
return 0 ;
}
當圖的邊數為e時,kruskal演算法所需的時間是o(eloge)。當e = ω(n^2)時,kruskal演算法比prim演算法差;但當e = o(n^2)時,kruskal演算法比prim演算法好得多。
給定無向連同帶權圖g = (v,e),v = 。kruskal演算法構造g的最小生成樹的基本思想是:
(1)首先將g的n個頂點看成n個孤立的連通分支。將所有的邊按權從小大排序。
此時,已構成g的一棵最小生成樹。
kruskal演算法的選邊過程:
1 -> 3 : 1
4 -> 6 : 2
2 -> 5 : 3
3 -> 4 : 4
2 -> 3 : 5
實現:
#include #include #include #include using namespace std ;
struct treenode
friend
bool operator < (const treenode& lth, const treenode& rth)
public:
int m_nvertexindexa ;
int m_nvertexindexb ;
int m_nweight ;
} ;// 並查集
class unionset
// 合併i,j。如果i,j同在集合中,返回false。否則返回true
bool union (int i, int j)
else
}private:
// 初始化並查集
int __init()
// cout << endl ;
return 0 ;
}// 查詢index元素的父親節點 並且壓縮路徑長度
int __find (int nindex)
return m_nvfather[nindex] = __find (m_nvfather[nindex]);
}private:
vectorm_nvfather ; // 父親陣列
vector::size_type m_nsetelecount ; // 集合中結點個數
} ;class mst_kruskal
void dokruskal ()
}// 輸出結果
for (size_t i = 0; i < m_tnmstree.size() ; ++ i)
}private:
void __getminheap (const vector>& graph) }}
}private:
vectorm_tnmstree ;
int m_nnodecount ;
minheap m_minheap ;
} ;int main ()
graph[0][1]= 6 ;
graph[0][2] = 1 ;
graph[0][3] = 3 ;
graph[1][2] = 5 ;
graph[1][4] = 3 ;
graph[2][3] = 5 ;
graph[2][4] = 6 ;
graph[2][5] = 4 ;
graph[3][5] = 2 ;
graph[4][5] = 6 ;
graph[1][0]= 6 ;
graph[2][0] = 1 ;
graph[3][0] = 3 ;
graph[2][1] = 5 ;
graph[4][1] = 3 ;
graph[3][2] = 5 ;
graph[4][2] = 6 ;
graph[5][2] = 4 ;
graph[5][3] = 2 ;
graph[5][4] = 6 ;
mst_kruskal mst (graph);
mst.dokruskal () ;
}
**: 最小生成樹 次小生成樹
一 最小生成樹 說到生成樹首先要解釋一下樹,樹是乙個聯通的無向無環圖,多棵樹的集合則被稱為森林。因此,樹具有許多性質 1.兩點之間的路徑是唯一的。2.邊數等於點數減一。3.連線任意兩點都會生成乙個環。對於乙個無向聯通圖g的子圖,如果它包含g的所有點,則它被稱為g的生成樹,而各邊權和最小的生成樹則被稱...
最小生成樹
package 圖 最小生成樹是用最少的邊吧把所有的節點連線起來。於是和圖的深度優先搜素差不多。class stack public void push int key public int pop 檢視棧頂的元素 public int peek public boolean isempty cla...
最小生成樹
define max vertex num 20 最大頂點數 typedef int adjmatrix max vertex num max vertex num 鄰接矩陣型別 typedef char vertextype typedef struct mgraph struct dnodecl...