給定乙個 \(n\) 個頂點 \(m\) 條邊的帶權無向圖,多次詢問在兩個點之間所有可能的路徑中的最大值,最小為多少。
顯然,可以先在用 kruskal 演算法在原圖上構造一棵最小生成樹。可以證明,兩點之間的路徑在這棵樹上時,邊權的最大值最小。
而對於找到這個最大值有兩種做法,一種是在求最近公共祖先時記錄下路徑上的最大值;另一種作法是在構造生成樹時的並查集使用按秩合併優化,直接在並查集(注意不是在生成樹上)上求邊權的最大值。這裡主要介紹後一種作法。
所謂的秩,有兩種定義方法。一種是表示樹的深度(未路徑壓縮時),另一種是表示集合的大小。這裡可以定義為樹的大小。按秩合併就是把秩小的並查集合並為秩較大的並查集的兒子。最終得到的並查集會有樹形結構。同時為了維護這個樹形結構,就不能再使用路徑壓縮優化了。
而使用按秩合併後的並查集,每次查詢操作的均攤複雜度是 \(o(logn)\)。可以接受。
可以發現,在 kruskal 演算法中使用按秩合併優化時,如果在合併時記錄一下邊權,最終得到的並查集會有乙個很有意思的性質:在一條鏈上,深度越低的邊,邊權越大。
這是因為在構造最小生成樹的時候,如果一直是最初合併的子樹秩最大,那麼就會一直把新的那一條邊新增到這棵樹中,此時最終得到的並查集深度也就只有一層了。同時由於邊權從小到大的性質,任意兩個點之間的路徑中邊權最大值也一定在這兩個點到根節點的邊權其中之一。
而對於更一般的情況,如下圖中的的帶權無向圖。
按照 kruskal 演算法的流程,最終得到的帶權並查集(非生成樹)如下圖所示:
最終得到的並查集也滿足這個特殊性質。
設當前邊連線一棵子樹 \(a\) 和一棵子樹 \(b\)。由於最初依據邊權大小對邊進行了排序,所以這條邊的邊權一定比之前的任何一條邊都要大。
當 \(a\) 的秩比 \(b\) 小時,就會將 \(a\) 的樹根連線到 \(b\) 的樹根上,而這條邊的邊權就是這條最大的邊權, 所以 \(a\) 向 \(b\) 連的這條邊肯定比 \(a\) 中的任何一條邊的邊權都要大。
當 \(a\) 的秩比 \(b\) 大時,同樣也滿足新的這條邊比 \(b\) 中任意一條邊的邊權都大,也就滿足了最初提到的性質。(這裡只是簡單的證明了一下,並未嚴格證明)
因為我們只關心路徑上最大邊權的最小值,並不關心這條路徑怎麼走。故雖然在按秩合併時破壞了兩點之間路徑的順序,但是在最小生成樹中已經保證了兩點之間必定聯通,所以並不會對答案產生影響。
於是可以根據以上的性質。對於 \(x,y\) 兩點,先以 \(x\) 為起點向上走,同時記錄路徑上經過的每乙個點之前的邊權(後面會提到用處)。以及邊權的最大值,由於上面提到的性質,最大值直接更新就好了,不需要比較。
再以 \(y\) 為起點向上走,同樣也記錄邊權的最大值,如果遇到了某乙個節點,該節點經過之前的邊權已經被賦值了,那麼就說明有兩種情況。要麼就是 \(x\) 和 \(y\) 在同一條鏈上,但是不知道誰的深度更大,如果 \(y\) 在 \(x\) 的下面,那麼搜到的這個節點就是 \(x\) 本身了,但是這個節點向下的邊權是沒有記錄的,所以答案需要取當前這個點向下的最大值和路徑上的最大值較大的那個;要麼就是已經搜到了根節點,在此時需要取從 \(x\) 往上走的最大值和從 \(y\) 往上走的最大值較大的那個。所以此處的取 \(max\) 是不可省略的。
最終還要注意一下題目中要求的輸出格式,就可以通過本題了。
#include#includeusing namespace std;
const int n=5e4+10;
const int m=1e5+10;
int f[n],cnt[n],n,m,vis[n],val[n],q;
struct edge
}int nlc(int x,int y)
now=y;
while(!nlcakioi)
if(now==f[now]) break;
ans2=val[now];
now=f[now];
} return ans2;
}int main()
} return 0;
}
UVA 11354 Bond(最小瓶頸路 倍增)
題意 問圖上任意兩點 u,v 之間的路徑上,所經過的最大邊權最小為多少?求最小瓶頸路,既是求最小生成樹。因為要處理多組詢問,所以需要用倍增加速。先處理出最小生成樹,prim的時間複雜度為o n n kruskal為o mlogm 前者適合處理稠密圖,後者適合處理稀疏圖。這裡的倍增處理是值得記住的,在...
並查集 並查集
本文參考了 挑戰程式設計競賽 和jennica的github題解 陣列版 int parent max n int rank max n void init int n int find int x else void union int x,int y else 結構體版 struct node ...
UVA 1160(簡單建模 並查集)
題意 有n種化合物,每種化合物由兩種元素組成。當幾種的化合物數量等於他們所含不同元素的數量時,就會發生 現在依次給出化合物的組成,當新的化合物與之前的化合物放在一起會發生 時,就不能允許這個化合物放進來。輸出拒絕的次數。思路 把元素看成點,化合物看成邊,每次新的化合物進來當成連一條邊。如果圖中沒有環...