目錄算是最後幾個完成這一章節學習的了,有很多思想和技巧都很好,需要好好學習
主要涉及兩個演算法: \(prim\) 演算法和 \(kruskal\) 演算法
感謝lsp為本文訂正做出的貢獻!
先跑一遍 \(dij\) 求出 \(d_i\),再遍歷每個點,統計有幾種修建方案
然後根據乘法原理,求出所有方案數即可
(感覺和最小生成樹沒半毛錢關係是吧
code
要求將整個圖的節點通電,所以發電站一定要有,並要結合電網來達到最小花費。
想象一下,電從哪來?不能憑空產出,只能從外邊接(感性理解/cy)
所以可以建乙個虛點(總電源),發電站只有連線總電源才能通電。
所以這個題就轉化成,另設乙個虛點將所有節點連線,然後建乙個總的最小生成樹的板子題了
code
因為給出的資料一定是最小生成樹,所以直接開始建樹
在建樹過程中,每一次合併當成兩個聯通塊相連
因為要求構成完全圖,設兩個相連的聯通快分別為 \(cnt_i\) 和 \(cnt_j\) 那麼兩個聯通塊之間最多能連 \(cnt_i \times cnt_j - 1\) 條邊(因為最小生成樹的邊已經統計過一次了所以要減一)
要求最小生成樹唯一,所以這些邊的邊權是對應的 \(e[i].w + 1\),統計後兩個聯通快記得和成乙個聯通塊
考慮建樹邊統計答案這種做法的正確性:其中的任何一條邊都不可能作為最小生成樹的一條邊,因為有比他更優的邊已經連線了兩個聯通塊(模擬 \(kruskal\) 的貪心原理,可能這道題就是為了理解這個演算法的原理而存在的)
code
本質同嚴格次小生成樹,只是資料範圍略有不同
牛奶運輸不是嚴格次小,不過用嚴格次小的**竟然也能過/jk
大體思路:建出最小生成樹 \(\to\) 用 \(lca\) 預處理最大值的次大值 \(\to\) 遍歷所有不在最小生成樹上的邊,記錄統計後的答案哪個更小 \(\to\) 切掉此題
code
一開始考慮先用白邊生成樹,再用黑邊生成樹。如果這樣做的話,生成的樹可能不是聯通的。換一種說法就是有可能有不是很優的白邊也可以在生成樹上。
乙個很奇妙的思路:
二分乙個值,讓白邊減掉這個權值,然後跑最小生成樹,當所用數量剛好等於白邊並且權值最小時就是答案。注意最後的答案要加上減去的權值
正確性:通過改變白邊的權值來改變白邊在所有邊中的位置,減得越多白邊在排序中越靠前,在最小生成樹中的數量也越多,反之越少。因此具有單調性,可以二分出最恰當的那個要減得權值
code
考慮一棵最小生成樹中,如果有其他建樹方式,為了保證權值和不變,那麼新加的邊與減掉的邊邊權一定是相同的
那麼我們統計出所有邊權相同的邊,並將他們分組放在一起。根據最小生成樹的貪心思想,先連小邊再連大邊。每連一種權值的邊,爆搜有多少種連邊方式。最後根據乘法原理統計答案即可
我在想乙個正確性:有沒有一種情況,能把兩條邊同時替換為一大一小的兩條邊也能使其成為一棵最小生成樹
證明:一開始就是從小到大連邊,所以小的邊的情況已經統計上了,這種情況在一次建樹後就不可能出現(題目中說無重邊和子環也是乙個前提
code
最小生成樹演算法總結
首先,最小生成樹是建立在無向圖中的,對於乙個有n個點的圖,最少需要n 1條邊使得這n個點進行連通,由這n 1條邊組成的子圖稱為原圖的生成樹,乙個圖的生成樹並不是唯一的。最小生成樹則是樹中權值之和最小的一顆生成樹,最小生成樹也可能不唯一。最小生成樹一般有兩種演算法,一種是prim演算法,另一種是kru...
最小生成樹 kruskal c 演算法 總結
首先,什麼是kruskal演算法 克魯斯卡爾演算法 kruskal s algorithm 是兩個經典的最小生成樹演算法的較為簡單理解的乙個。這裡面充分體現了貪心演算法的精髓。大致的流程可以用乙個圖來表示。這裡的圖的選擇借用了wikipedia上的那個。非常清晰且直觀。首先第一步,我們有一張圖,有若...
最小生成樹演算法總結 Kruskal,Prim
今天覆習最小生成樹演算法。最小生成樹指的是在乙個圖中選擇n 1條邊將所有n個頂點連起來,且n 1條邊的權值之和最小。形象一點說就是找出一條路線遍歷完所有點,不能形成迴路且總路程最短。kurskal演算法的核心思想是將邊按權值排序,每次選出權值最小的邊,只要不會形成迴路就加入結果集,如果形成了迴路就不...