題目:
碼了乙個星期終於過了這一題。(渣是原罪...)
最小生成樹+倍增lca
思路不難,但這是我第一次寫lca的題目。下面一步步來解釋這題。
題意:給你m條無向邊,有k個查詢,問從a到b所有路徑上的最長邊的最小值。
首先,從a到b所有路徑上的最長邊的最小值所對應的邊一定在最小生成樹上。
為什麼?
現在來回憶一下kru的做法。把所有邊從小到大排序,接著從小到大使用這些邊去聯通每個點,當使用一條邊x時,若x的兩個端點在此之前已經聯通,則說明這兩個點在此之前已經被更短的邊聯通。可以想象,最小生成樹上每兩個點都是被最短的邊聯通的。即當兩個點聯通時的最長邊不可能更小。
所以,現在問題轉化為從a到b的在最小生成樹上的路徑的最長邊是多少。
可知從a到b的最長邊等於max(a->最近公共祖先c的最長邊,b->c的最長邊),即題目轉化為lca問題。
至此,思路就很明確了。先構建最小生成樹,再尋找兩個點的最近公共祖先。
本蒟蒻用倍增lca尋找最近公共祖先,關於倍增lca的解釋可以看以下部落格(
我們設mx[i][j]表示點i到fa[i][j]的最長邊,與fa[i][j]=fa[fa[i][j-1]][j-1]相似mx[i][j]=max(mx[i][j-1],mx[fa[i][j-1]][j-1]),即點i到fa[i][j]的最長邊等於點i到fa[i][j-1]的最長邊與點u(fa[i][j-1])到點fa[u][j-1]的最長邊的最大值。(如圖)
{ for(int i=0; i後記:
這道題聽師兄說是可以直接構造出最小生成樹,構造的時候和並查集一樣,按秩合併,就能保證樹高是logn的,就不用寫倍增lca了。但是本蒟蒻實在是太渣了,寫了很久都還是tle,有興趣的大佬可以試一下,隨便教下弱弱的我。
bzoj3732 最小生成樹 倍增
顯然使a到b的最長邊最小的路徑一定在最小生成樹上,否則一定可以使生成樹更小。求出原圖的最小生成樹,然後用倍增求路徑上最大值就可以了。1 include2 include3 include4 include5 using namespace std 6 define n 15010 7 define ...
bzoj3732 最小生成樹 倍增
顯然使a到b的最長邊最小的路徑一定在最小生成樹上,否則一定可以使生成樹更小。求出原圖的最小生成樹,然後用倍增求路徑上最大值就可以了。1 include2 include3 include4 include5 using namespace std 6 define n 15010 7 define ...
最小生成樹 次小生成樹
一 最小生成樹 說到生成樹首先要解釋一下樹,樹是乙個聯通的無向無環圖,多棵樹的集合則被稱為森林。因此,樹具有許多性質 1.兩點之間的路徑是唯一的。2.邊數等於點數減一。3.連線任意兩點都會生成乙個環。對於乙個無向聯通圖g的子圖,如果它包含g的所有點,則它被稱為g的生成樹,而各邊權和最小的生成樹則被稱...