可持久化並查集(一) 從阿克曼函式到映象

2021-07-27 11:35:28 字數 2233 閱讀 2081

noip2010

以下題目可以跳過。

(prison.pas/c/cpp)

【問題描述】

s 城現有兩座監獄,一共關押著n 名罪犯,編號分別為1~n。他們之間的關係自然也極不和諧。很多罪犯之間甚至積怨已久,如果客觀條件具備則隨時可能爆發衝突。我們用「怨氣值」(乙個正整數值)來表示某兩名罪犯之間的仇恨程度,怨氣值越大,則這兩名罪犯之間的積怨越多。如果兩名怨氣值為c 的罪犯被關押在同一監獄,他們倆之間會發生摩擦,並造成影響力為c 的衝突事件。

每年年末,警察局會將本年內監獄中的所有衝突事件按影響力從大到小排成乙個列表,然後上報到s 城z 市長那裡。公務繁忙的z 市長只會去看列表中的第乙個事件的影響力,如果影響很壞,他就會考慮撤換警察局長。

在詳細考察了n 名罪犯間的矛盾關係後,警察局長覺得壓力巨大。他準備將罪犯們在

兩座監獄內重新分配,以求產生的衝突事件影響力都較小,從而保住自己的烏紗帽。假設只要處於同一監獄內的某兩個罪犯間有仇恨,那麼他們一定會在每年的某個時候發生摩擦。那麼,應如何分配罪犯,才能使z 市長看到的那個衝突事件的影響力最小?這個最小值是多少?

【輸入】

輸入檔名為prison.in。輸入檔案的每行中兩個數之間用乙個空格隔開。

第一行為兩個正整數n 和m,分別表示罪犯的數目以及存在仇恨的罪犯對數。

接下來的m 行每行為三個正整數aj,bj,cj,表示aj 號和bj 號罪犯之間存在仇恨,其怨

氣值為 cj。資料保證 a b n j j 1 ≤ < ≤ ,0 < ≤ 1,000,000,000 j c ,且每對罪犯組合只出現一

次。 【輸出】

輸出檔案prison.out 共1 行,為z 市長看到的那個衝突事件的影響力。如果本年內監獄中未發生任何衝突事件,請輸出0。

【輸入輸出樣例】

prison.in、

4 6

1 4 2534

2 3 3512

1 2 28351

1 3 6618

2 4 1805

3 4 12884

prison.out

3512

【輸入輸出樣例說明】

罪犯之間的怨氣值如下面左圖所示,右圖所示為罪犯的分配方法,市長看到的衝突事件

影響力是3512(由2 號和3 號罪犯引發)。其他任何分法都不會比這個分法更優。

【資料範圍】

對於30%的資料有n≤ 15。

對於70%的資料有n≤ 2000,m≤ 50000。

對於100%的資料有n≤ 20000,m≤ 100000。

二分暴力可以過,然而我用並查集。開乙個映象n來代表當f[x]!=f[y]時若將其連線的情況。

#include

#include

#include

using

namespace

std;

int f[60010],n,m;

struct node

}p[100010];

int find(int x)

int main()

f[x]=find(p[i].y+n),f[y]=find(p[i].x+n);

}cout

<<0

0;}

通過上面的一道noip半水題,我們可以發現乙個問題,就是並查集的複雜度?不是o(n)吧。

阿克曼函式普及並查集知識。

正常來說,並查集的複雜度是很優的,至少比二分貪心o(nl

ogn2

)要好很多。

並查集進行n次查詢的時間複雜度是o(n )(執行n-1次合併和m≥n次查詢)。其中 是乙個增長極其緩慢的函式,它是阿克曼函式(ackermann function)的某個反函式。它可以看作是小於5的。所以可以認為並查集的時間複雜度幾乎是線性的。

這個中二的名字就是接下來我要重點講訴的東西,它以多一倍的空間表示了在原有基礎上,i的i』(虛擬id),如果任何j指向i時都指向i』那麼i變動時不就不會印象j的指向?

預知後事如何,請看下回分解:

可持久化並查集(二)——從映象到動態

可持久化並查集

n個集合 m個操作 1 a b 合併a,b所在集合 2 k 回到第k次操作之後的狀態 查詢算作操作 3 a b 詢問a,b是否屬於同一集合,是則輸出1否則輸出0 所給的a,b,k均經過加密,加密方法為x x xor lastans,lastans是上一次的輸出答案 並查集實質是乙個陣列,可持久化並查...

可持久化並查集

可持久化陣列 可持久化陣列是一種可以回退,訪問之前版本的陣列 是一些其他可持久化資料結構的基石 例如可持久化並查集 與普通並查集不同的是 這裡用到了 按秩合併新增鏈結描述 include const int n 2e5 7 int rootfa n rootdep n cnt,tot struct ...

可持久化並查集

點此看題 並查集最重要的就是fafa fa陣列,我們可以拿主席樹來維護這個fafa fa,並且每次改點只需要改乙個,為保證時間複雜度我們再維護乙個dep depde p來做啟發式合併,這就變成了乙個單點修改,單點查詢的主席樹了。include include using namespace std ...