簡單來說,並查集的主要操作有:
1-合併兩個不相交的集合
2-查詢兩個元素是否屬於同乙個集合
nkoj 1205 親戚或許你並不知道,你的某個朋友是你的親戚。他可能是你的曾祖父的外公的女婿的外甥女的表姐的孫子。如果能得到完整的家譜,判斷兩個人是否親戚應該是可行的,但如果兩個人的最近公共祖先與他們相隔好幾代,使得家譜十分龐大,那麼檢驗親戚關係實非人力所能及。在這種情況下,最好的幫手就是計算機。
為了將問題簡化,你將得到一些親戚關係的資訊,如同marry和tom是親戚,tom和ben是親戚,等等。從這些資訊中,你可以推出marry和ben 是親戚。請寫乙個程式,對於我們的關於親戚關係的提問,以最快的速度給出答案。
輸入格式:
輸入由兩部分組成。
第一部分以n,m開始。n為問題涉及的人的個數(1 ≤ n ≤ 20000)。這些人的
編號為1,2,3,…,n。下面有m行(1 ≤ m ≤ 100000),每行有兩個數ai, bi,表示已知ai和bi是親戚。
第二部分以q開始。以下q行有q個詢問(1 ≤ q ≤ 1 000 000),每行為ci,di,表示詢問ci和di是否為親戚。
輸出格式:
對於每個詢問ci, di,若ci和di為親戚,則輸出yes,否則輸出no。
樣例輸入:
10 7
2 4
5 7
1 3
8 9
1 2
5 6
2 3
33 4
7 10
8 9
樣例輸出:
yesno
yes傳送門:
從題目中我們可以得到一些提示,它就是要讓我們構建乙個關係集合出來,再快速查詢兩個元素是否位於同一集合,這顯然就與並查集的效用十分吻合。
基於此演算法如此高的時間複雜度,我們採用某種特殊的手段來優化它,這也便是並查集的核心內容——路徑壓縮
查詢同時路徑壓縮
int getfather(int v)
}
合併兩個集合void merge(int x, int y)
我們回到引例,我們現在可以很輕鬆地解決此題(偽**)——for (i = 1; i <= n; ++ i)father[i] = i; //初始化
for (i = 1; i <= m; ++ i)
for (i = 1; i <= q; ++ i) (o(m))
#######提供幾道並查集的簡單練習:
nkoj 3197 島嶼
nkoj 1046 關押罪犯
簡言之,最小生成樹就是在乙個連通圖中生成一棵樹,剛好連通所有節點,所含邊數(或邊權總和最小)。
舉個栗子,感受一下——
引例:村長的難題關注這個例子,我們的解法是要用網線連線n戶人家,找出一種方案,使得總的長度最少。我們目測可到樣圖的最小生成樹何老闆是某鄉村的村長,何老闆打算給該村的所有人家都連上網。
該村有n(1<=n<=1000)戶人家,編號1到n。由於地形等原因,只有
m(1<=m<=50000)對人家之間可以相互牽線。在不同人家間牽線的長度不一定相同。比如在ai與bi之間牽線需要ci公尺長的網線。
整個村的網路入口在1號人家,何老闆的問題是:是否能使得所有人家都連上網?使所有人家都連上網,最少需要多少公尺網線?
接下來我會介紹三種演算法:
1-kruskal(克魯斯卡爾演算法)
2-prim(普里姆演算法)
3-boruvka演算法
這三種演算法都是基於貪心思想的應用,但其中kruskal可處理同權邊的情況,而boruvka不可以。
kruskal演算法的基本思想:
每次選不屬於同一生成樹的且權值最小的邊的頂點,將邊加入生成樹,並將所在的2個生成樹合併,直到只剩乙個生成樹。以下是用kruskal解決引例的**:排序使用quicksort
檢查是否在同一生成樹用並查集
總時間複雜度o(mlogm),其中m表示邊的數量
#define maxm 10003
#define maxn 103
struct node edge[maxm]; //邊的資訊
int n, m; //n為頂點數,m為邊數
int father[maxn]; //father存i的父親節點
bool cmp(node a, node b)
void ini()
int getfather(int x)
void kruskal()
} printf("%d", tot);
} int main()
prim演算法的基本思想:任選乙個點,加入生成樹集合。以下給出prim函式**:在未加入生成樹的點中,找出離生成樹距離最近的乙個點,將其加入生成樹。
反覆上述操作,直到所有點都加入了生成樹。
總時間複雜度o(n^2),其中n為點的個數
void prim(int x)
for (i = 1; i <= n - 1; ++ i)
dis[k] = 0;
for (j = 1; j <= n; ++ j)
if( dis[j] > map[j][k])
} }
並查集(最小生成樹)
時間限制 1000 ms 記憶體限制 65536 kb 題目描述 有一張城市地圖,圖中的頂點為城市,無向邊代表兩個城市間的連通關係,邊上的權為在這兩個城市之間修建高速公路的造價,研究後發現,這個地圖有乙個特點,即任一對城市都是連通的。現在的問題是,要修建若干高速公路把所有城市聯絡起來,問如何設計可使...
最小生成樹 並查集練習
叢林中的路 熱帶島嶼lagrishan的首領現在面臨乙個問題 幾年前,一批外援資金被用於維護村落之間的道路,但日益繁茂的叢林無情的侵蝕著村民的道路,導致道路維修開銷巨大,長老會不得不放棄部分道路的維護。已經知道了每條路每個月的維修費用 單位為aacms 現在長老會需要提出一種方案,即需要保證村落之間...
並查集 最小生成樹(prim kruskal)
並查集,從名字上來看可以知道,是乙個集合,而且這個集合可以合併和查詢。查詢,主要是查詢集合中的某乙個元素的祖先是誰,某一些元素是不是擁有相同的祖先。合併,是把兩個不想交的集合合併為乙個集合。並查集的思想就是朋友的朋友就是朋友 雖然現實生活中並不是這樣 並查集的第一步初始化,自己是自己的祖先。乙個人來...