1. 程式人生 > >圖--生成樹和最小生成樹

圖--生成樹和最小生成樹

樹(自由樹)、無序樹和有根樹

     自由樹就是一個無迴路的連通圖(沒有確定根)(在自由樹中選定一頂點做根,則成為一棵通常的樹)。
     從根開始,為每個頂點(在樹中通常稱作結點)的孩子規定從左到右的次序,則它就成為一棵有序樹
     在圖的應用中,我們常常需要求給定圖的一個子圖,使該子圖是一棵樹。
生成樹

1、生成樹

     如果連通圖G的一個子圖是一棵包含G的所有頂點的樹,則該子圖稱為G的生成樹(SpanningTree)。
     生成樹是連通圖的包含圖中的所有頂點的極小連通子圖。
     圖的生成樹不惟一。從不同的頂點出發進行遍歷,可以得到不同的生成樹。

2、深度優先生成樹和廣度優先生成樹


(1)生成樹的求解方法
     設圖G=(V,E)是一個具有n個頂點的連通圖。則從G的任一頂點(源點)出發,作一次深度優先搜尋(廣度優先搜尋),搜尋到的n個頂點和搜尋過程中從一個已訪問過的頂點vi搜尋到一個未曾訪問過的鄰接點vj,所經過的邊(vi,vj)(共n-1條)組成的極小連通子圖就是生成樹。(源點是生成樹的根)
     通常,由深度優先搜尋得到的生成樹稱為深度優先生成樹,簡稱為DFS生成樹;由廣度優先搜尋得到的生成樹稱為廣度優先生成樹,簡稱為BPS生成樹。
  
(2)求DFS生成樹和BFS生成樹演算法
    只要在DFS(或DFSM)演算法的if語句中,在遞迴呼叫語句之前加入適當生成邊(vi
,vj)的操作(如將該邊輸出或儲存),即可得到求DFS生成樹的演算法。
    在BFS(或BFSM)演算法的if語句中,加入生成樹邊(vi,vj)的操作,可得到求BFS生成樹的演算法。【參見練習】
  注意:
    ①圖的廣度優先生成樹的樹高不會超過該圖其它生成樹的高度
    ②圖的生成樹不惟一,從不同的頂點出發進行遍歷,可以得到不同的生成樹。

3、生成樹的通用定義
    若從圖的某頂點出發,可以系統地訪問到圖中所有頂點,則遍歷時經過的邊和圖的所有頂點所構成的子圖,稱作該圖的生成樹。(此定義不僅僅適用於無向圖,對有向圖同樣適用。)
(1)若G是強連通的有向圖,則從其中任一頂點v出發,都可以訪問遍G中的所有頂點,從而得到以v為根的生成樹。
(2)若G是有根的有向圖,設根為v,則從根v出發可以完成對G的遍歷,得到G的以v為根的生成樹。
(3)若G是非連通的無向圖,則要若干次從外部呼叫DFS(或BFS)演算法,才能完成對G的遍歷。每一次外部呼叫,只能訪問到G的一個連通分量的頂點集,這些頂點和遍歷時所經過的邊構成了該連通分量的一棵DFS(或BPS)生成樹。G的各個連通分量的DFS(或BFS)生成樹組成了G的DFS(或BFS)生成森林。
(4)若G是非強連通的有向圖,且源點又不是有向圖的根,則遍歷時一般也只能得到該有向圖的生成森林。

5、普里姆(Prim)演算法
(1)演算法思想
     T=(U,TE)是存放MST的集合。
  ①T的初值是({r},¢)
    即最小生成樹初始時只有一個紅點r,沒有紅邊。
  ②T經過n-1次如下步驟操作,最後得到一棵含n個頂點,n-1條邊的最小生成樹
     ⒈選擇紫邊集中一條輕邊並擴充進T
  ⒉將輕邊連線的藍點改紅點
  ⒊將輕邊改紅邊
     ⒋修改紫邊集

(2)較小紫邊集的構造
     若當前形成的T中有k個頂點,|U|=k,|V-u|=n-k,故可能的紫邊數目是k(n-k)。從如此大的紫邊集中選擇輕邊是低效的。因此,必須構造較小的紫邊集。
     對於每個藍點v ∈V-U,從v到各紅點的紫邊中,只有最短的那一條才有可能是輕邊。因此,只須保留所有n-k個藍點所關聯的最短紫邊作為輕邊的候選集即可。

(3)候選紫邊集合的修改

     當把輕邊(u,v)擴充到T時,因為v由藍變紅,故對每個剩餘的藍點j,邊(v,j)就由非紫邊變為紫邊,這條新紫邊的長度可能小於藍點j原來所關聯的最短紫邊的長度。因此,用長度更小的新紫邊取代那些原有的最短紫邊。

(4)Prim演算法的虛擬碼描述

 PrimMST(G,T,r){
  //求圖G的以r為根的MST,結果放在T=(U,TE)中
    InitCandidateSet(…);//初始化:設定初始的輕邊候選集,並置T=({r},¢)
    for(k=0;k<n-1;k++){ //求T的n-1條樹邊
        (u,v)=SelectLiShtEdge(…);//選取輕邊(u,v);
         T←T∪{(u,v)};//擴充T,即(u,v)塗紅加入TE,藍點v並人紅點集U
        ModifyCandidateSet(…); //根據新紅點v調整候選輕邊集
      } 
   }

(5) 演算法的執行過程

     用PRIM演算法得到最小生成樹的過程【參見動畫演示


  注意:
     
若候選輕邊集中的輕邊不止一條,可任選其中的一條擴充到T中。
     連通網的最小生成樹不一定是惟一的,但它們的權相等。
    
(6)演算法特點
     該演算法的特點是當前形成的集合T始終是一棵樹。將T中U和TE分別看作紅點和紅邊集,V-U看作藍點集。演算法的每一步均是在連線紅、藍點集的紫邊中選擇一條輕邊擴充進T中。MST性質保證了此邊是安全的。T從任意的根r開始,並逐漸生長直至U=V,即T包含了 C中所有的頂點為止。MST性質確保此時的T是G的一棵MST。因為每次新增的邊是使樹中的權儘可能小,因此這是一種"貪心"的策略。
(7)演算法分析
     該演算法的時間複雜度為O(n2)。與圖中邊數無關,該演算法適合於稠密圖。

(1)演算法思想
  ①T的初始狀態
       只有n個頂點而無邊的森林T=(V,¢ )
  ②按邊長遞增的順序選擇E中的n-1安全邊(u,v)並加入T,生成MST
注意:
     安全邊指兩個端點分別是森林T裡兩棵樹中的頂點的邊。加入安全邊,可將森林中的兩棵樹連線成一棵更大的樹
     因為每一次新增到T中的邊均是當前權值最小的安全邊,MST性質也能保證最終的T是一棵最小生成樹。

(2)演算法特點
     該演算法的特點是:當前形成的集合T除最後的結果外,始終是一個森林。

(3)Kruskal演算法的抽象描述

  KruskalMST(G){//求連通網G的一棵MST
     T=(V,¢); //初始化,T是隻含n個頂點不包含邊的森林
    依權值的遞增序對E(G)中的邊排序,並設結果在E[0..e-1]中
    for(i=0;i<e;i++) { //e為圖中邊總數
        取E[0..e-1)中的第i條邊(u,v);
         if u和v分別屬於T中兩棵不同的樹then
            T=T∪{(u,v)};//(u,v)是安全邊,將其加入T中
         if T已是一棵生成樹then
      ``         return T;
        }//endfor
       return T;
   } 

(4)用Kruskal演算法構造最小生成樹的過程
     用Kruskal演算法構造最小生成樹的過程【參見動畫演示


(5)演算法分析

     該演算法的時間複雜度為O(elge)。
    Kruskal演算法的時間主要取決於邊數。它較適合於稀疏圖。




相關推薦

成樹小生成樹

一、生成樹的概念                 在一個任意連通圖G中,如果取它的全部頂點和一部分邊構成一個子圖G',即:V(G')=V(G)和E

--成樹小生成樹

樹(自由樹)、無序樹和有根樹      自由樹就是一個無迴路的連通圖(沒有確定根)(在自由樹中選定一頂點做根,則成為一棵通常的樹)。      從根開始,為每個頂點(在樹中通常稱作結點)的孩子規定從左到右的次序,則它就成為一棵有序樹。      在圖的應用中,我們常常需要求

幾分鐘搞明白成樹小生成樹的定義

注意文字意思:不管是生成樹還是最小生成樹一定還是輸,千萬別和圖混淆了。 下面來說生成樹:我們這棵樹是針對圖來說的,如果你們已經知道極小連通子圖就非常簡單了, 極小連通子圖什麼意思呢,就是我們把圖中的全部節點連線起來,假如n個節點那麼,邊是n - 1條。 注

成樹poj2377 (小生成樹一個原理,只是排序的時候要降序排列)

#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=1000+10; const int maxm=20000+10; struc

資料結構——的連通性(成樹小生成樹、生成森林)

1、求圖的生成樹(或生成森林)       生成樹:是一個極小連通子圖,它含有圖中全部n個頂點,但只有n-1條邊。       生成森林: 由若干棵生成樹組成,含全部頂點,但構成這些樹的邊是最少的。    

論經典演算法(通俗易懂):短路徑小生成樹

一、最短路問題 求圖的最短路問題,幾乎是圖論的必學內容,而且在演算法分析與設計中也會涉及。很多書上內容, 實在沒法看,我們的圖論教材,更是編的非常糟糕,吐槽,為啥要用自己學校編的破教材,不過據說 下一屆終於要換書了。 言歸正傳,開始說明最短路問題。

資料結構學習筆記(20)---的應用(成樹小生成樹

上一篇部落格寫了圖的基本儲存於遍歷,在此基礎上,此篇部落格將會介紹圖的主要應用—–生成樹與最小生成樹。 (一)生成樹 定義:我總感覺書上定義比較繁瑣,因此就自己簡單定義了一下(可能不對哦),生成樹其實就是:對於一棵樹G,若頂點數為n,則在原來圖的基礎上把

資料結構——(8)——小生成樹(MST)

問題的提出 如下圖,假設這裡有一系列的房屋,問如何鋪設電線,可以使得連線所有房屋的電線的總成本最低?這是20世紀20年代早期研究最小生長樹的最初動機。 (捷克數學家OtakarBorůvka完成的工作)。 最短路徑樹與最小生成樹(MST) 上次,我們看到了Dijkstra演

資料結構實驗之論九:小生成樹__Prim

Problem Description 有n個城市,其中有些城市之間可以修建公路,修建不同的公路費用是不同的。現在我們想知道,最少花多少錢修公路可以將所有的城市連在一起,使在任意一城市出發,可以到達其他任意的城市。 Input 輸入包含多組資料,格式如下。 第一行包括兩個整數n m,

資料結構實驗之論九:小生成樹 (SDUT 2144)

#include<bits/stdc++.h> using namespace std; typedef long long ll; struct node { int s, e; int w; }s[100005]; int c[105]; bool cmp(str

論六:小生成樹

問題描述:在無向圖中找出一個最小生成樹,前提是圖是連通的。 一、Prim演算法 1、思路:貪心,每次更新每個節點的距離,使這個節點的距離最短,類似於dijkstra演算法 2、使用條件:無向連通圖 3、演算法實現: (1)找到一個起始點,(終點有沒有都無所謂),將起點的距離設為0(表示起點到起點的距

一個的兩棵小生成樹,邊的權值序列排序後結果相同

情形2樹A中並不包含邊bi,則把bi加到樹A上,形成一個圈,由於A是最小生成樹,這個圈裡任意一條邊的權值都不大於w(bi) ,另外,這個圈裡存在邊aj不在樹B中。因此,有w(aj)≤w(bi),且j>i (因為aj不在B中)。於是,有w(bi)≤w(ai)≤w(aj)≤w(bi),因此w(ai)= w(

Prim輸出無向中所有的小生成樹

思路: 給出n個頂點m條邊。一棵最小生成樹中有n-1條邊,所以在m條邊中選n-1條邊判斷能否構成最小生成樹,如果能則直接輸出。 判斷是否能構成最小生成樹的條件是 當前的n-1條邊的權值的和是否是最小生成樹的權值的和(程式碼裡的ans)。 步驟: 先進行一

例題:短網路 論演算法之小生成樹 prim//kruskal 學習筆記

圖論演算法之最小生成樹  prim//kruskal         最小生成樹簡單的說就是在一個圖裡選取一些邊,使這些邊以及它們所連線的結點組成一棵樹(兩兩結點之間可以到達),並且使選取的邊的邊權最

51nod 1212 無向小生成樹小生成樹

 收藏  關注 N個點M條邊的無向連通圖,每條邊有一個權值,求該圖的最小生成樹。 Input 第1行:2個數N,M中間用空格分隔,N為點的數量,M為邊的數量。(2 &

任務排程小生成樹

排程問題: 問題背景:一個共享資源,多個job要訪問。 question:那我們應該如何排列job的順序 假定:每個job 有優先順序 ,和需要使用資源的時間長度當我們排列所有job之後,每個job都會有一個開始時間和結束時間,那麼如何評定一個方案是不是好方案 ,/

的應用(小生成樹、拓撲排序、關鍵路徑)

一:求最小生成樹 應用場景:例如要在n個城市之間鋪設光纜,主要目標是要使這 n 個城市的任意兩個之間都可以通訊,但鋪設光纜的費用很高,且各個城市之間鋪設光纜的費用不同,因此另一個目標是要使鋪設光纜的總費用最低。這就需要找到帶權的最小生成樹。 普里姆演算法:

(Graph)——小生成樹短路徑、Kruskal、Dijkstra、Floyd

4. 最小生成樹 4.1 生成樹 (1)定義:所有頂點均由邊連線在一起,但不存在迴路的圖叫該圖的生成樹 (2)深度優先生成樹與廣度優先生成樹 (3)     一個圖可以有許多棵不同的生成樹    所有

資料結構之二(小生成樹--普里姆演算法)

1 #include <iostream> 2 #include "SeqList.h" 3 #include <iomanip> 4 using namespace std; 5 6 #define INFINITY 65535 7 8 t

的兩種小生成樹演算法之C++封裝

最小生成樹定義:     給定一無向帶權圖,頂點數是n,要使圖連通只需n-1條邊,若這n-1條邊的權值和最小,則稱有這n個頂點和n-1條邊構成了圖的最小生成樹(minimum-cost spanning tree)MST。 兩種最小生成樹演算法: 一、prim演算法