在講最小生成樹之前,先來說一說開放樹。連通而無環路的無向圖稱做開放樹
。如果指定開放樹中某一頂點為根,並且把每一條邊看成是背離根的,則一棵開放樹變成一棵樹。
開放樹有2個性質:
如下列兩個圖:
只針對無向圖
假設e中的每條邊都有權重,為c(u,v),也叫做邊長。圖g的一棵生成樹是連線v中所有頂點的一棵開放樹。將生成樹中所有邊長的總和稱為生成樹的價。使這個價最小的生成樹稱為圖的最小生成樹
。
設g=(v,e)是乙個連通圖,在e上定義乙個權函式c,且是g的任意生成森林,令
其中,|t| <= |e|,又假設e=(v,w)是e-t中的一條邊,其權值c[v][w]最小,而且v在v1中,w不在v1中,則圖g有一棵包含t和e的生成樹,其價不大於包含t的任何生成樹的價。
以上的性質下,兩種演算法應運而生:prim演算法和kruskal演算法
/*輸入為加權無向圖g=(v,e),其中v=
要點:引進集合u和t,u準備放頂點,t準備放邊。初值為u=,t為空,選擇最小權的邊(u,v),使u在u中,v在v-u中,將v加入u,(u,v)加入t。重複這個過程 */
void prim(costtype c[n+1][n+1])
for(i=2;i=n;i++)
cout
prim演算法複雜度為o(n2),而kruskal演算法複雜度為o(ne),故prim演算法適用於點較少的情況
只針對有向圖
首先為除根之外的每個點選定一條入邊,這條入邊一定要是所有入邊中最小的。現在所有的最小入邊都選擇出來了,如果這個入邊集不存在有向環的話,我們可以證明這個集合就是該圖的最小樹形圖。這個證明並不是很難。如果存在有向環的話,我們就要將這個有向環縮成乙個人工頂點,同時改變圖中邊的權。假設某點u在該環上,並設這個環中指向u的邊權是in[u],那麼對於每條從u出發的邊(u, i, w),w為權,在新圖中連線(new, i, w)的邊,其中new為新加的人工頂點; 對於每條進入u的邊(i, u, w),在新圖中建立邊(i, new, w-in[u])的邊。
//檢查e0
for( i=1; i
if( !j) continue; //沒有找到環。
i=j;//將整個環的權值儲存,累計入原圖的最小樹形圖
dowhile( j!=i);
j=i;//對於環上的點有關的邊,修改邊權
do
j=pre[j];
}while( j!=i);
//縮點,將整個環縮成i號點,所有環上的點有關的邊轉移到點i
for( j=0; j
} //標記環上其他的點為被縮掉 下次再找ei時不參與
for( j=pre[i]; j!=i; j=pre[j])
falg[j]=true;
//當前環縮點結束,形成新的圖g',跳出繼續求g'的最小樹形圖 ,累計入sum。
}
if( i==n)
}
return sum;
}
最小生成樹 次小生成樹
一 最小生成樹 說到生成樹首先要解釋一下樹,樹是乙個聯通的無向無環圖,多棵樹的集合則被稱為森林。因此,樹具有許多性質 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...