Fzu 2155 盟國 並查集的增刪 裸題

2021-08-02 08:39:25 字數 1371 閱讀 3219

problem 2155 盟國

世界上存在著n個國家,簡單起見,編號從0~n-1,假如a國和b國是盟國,b國和c國是盟國,那麼a國和c國也是盟國。另外每個國家都有權宣布退盟(注意,退盟後還可以再結盟)。

定義下面兩個操作:

「m x y」 :x國和y國結盟

「s x」 :x國宣布退盟

多組case。

每組case輸入乙個n和m (1 ≤ n ≤ 100000 , 1 ≤ m ≤ 1000000),n是國家數,m是運算元。

接下來輸入m行操作

當n=0,m=0時,結束輸入

對每組case輸出最終有多少個聯盟,格式見樣例。

5 6

m 0 1

m 1 2

m 1 3

s 1m 1 2

s 33 1

m 1 2

0 0case #1: 3

case #2: 2

思路:如果在學完並查集並且專心刷過專題的同學們對這種題肯定是不陌生的。

我們如果直接暴力將宣布退出聯盟的國家拆除的話,會改變原來樹的形狀,使得原本屬於同一集合的點,find(i)不相等。

所以我們只要能夠保留原來樹的形狀即可。

那麼對於退出聯盟的國家,我們新建立乙個點,作為這個點的當前節點。我們不再去使用之前的這個國家所用的編號,而是用當前新建立出來這個點作為之後操作當前國家使用的編號。

我們維護乙個陣列now【i】表示當前節點i所代表的編號。

那麼這樣就鞥能夠保留原來樹的形狀並且不會影響之後的操作了。

另外注意一點,在查詢結果的時候,我們要注意因為有點可能原來是乙個祖先節點,所以我們並不能統計f【now【i】】==now【i】(find(now【i】)==now【i】)的點的數量。而是我們要統計祖先的種類數。

ac**:

#include#include#includeusing namespace std;

int f[1200500];

int now[1200500];

int vis[1200500];

int find(int a)

return r;

}int merge(int a,int b)

return 0;

}int main()

{ int n,m;

int kase=0;

while(~scanf("%d%d",&n,&m))

{if(n==0&&m==0)break;

int pos=n;

for(int i=0;is;

memset(vis,0,sizeof(vis));

for(int i=0;i

fzu 2155 盟國 並查集的增刪

description 世界上存在著n個國家,簡單起見,編號從0 n 1,假如a國和b國是盟國,b國和c國是盟國,那麼a國和c國也是盟國。另外每個國家都有權宣布退盟 注意,退盟後還可以再結盟 定義下面兩個操作 m x y x國和y國結盟 s x x國宣布退盟 input 多組case。每組case輸...

帶刪除並查集 FZU 2155 盟國

今天在安靜的草坪上寫這些東西,相對於其他地方,心理能夠寧靜下來許多,就是稍微有點冷了。帶刪除的並查集。方法是將初始化father i i的,用陣列代替,這樣可以回溯到刪除時的初始狀態了。時間卡的略微拙計。include include include include include using na...

FZU2155 盟國 (並查集的虛擬節點)

有關並查集中元素的刪除問題,刪除其中乙個元素的話雖其他元素之間的關係式沒有影響的,這點一定要注意,要解決這個問題,可以不動原來的節點,而建立乙個對映,是那些刪掉的幾點對映到乙個更大得數,用陣列來記錄,當他要再次合併時,只要查詢他的對映關係即可,最後統計一下。include includeint fa...