合縱連橫
時間限制:
1000
ms |
記憶體限制:
65535kb
難度:3
描述
亂世天下,諸侯割據。每個諸侯王都有一片自己的領土。但是不是所有的諸侯王都是安分守己的,實力強大的諸侯國會設法吞併那些實力弱的,讓自己的領土面積不斷擴大。而實力弱的諸侯王為了不讓自己的領土被吞併,他會聯合一些其他同樣弱小的諸侯國,組成聯盟
(聯盟不止乙個
),來共同抵抗那些強大的諸侯國。 強大的諸侯國為了瓦解這些聯盟,派出了最優秀的間諜來離間他們,使一些諸侯國退出聯盟。最開始,每個諸侯國是乙個聯盟。
有兩種操作 1
、u x y 表示x
和y在同乙個
聯盟。(0≤x
,y) 2
、d x 表示x
退出聯盟。
輸入
多組測試資料
第一行兩個數,n和
m(1 ≤ n≤ 10^5, 1 ≤ m ≤10^5
),分別表示諸侯國的個數和操作次數。
接下來有
m行操作
輸出
輸出聯盟的個數
樣例輸入
5 7
u 0 1
u 1 2
u 0 3
d 0u 1 4
d 2u 0 2
10 1
u 0 9
樣例輸出
case #1: 2
case #2: 9
這道題一讀題,應該都能想到要用並查集歸併集合。這道需要實現並查集的刪除操作。那麼問題就來了,並查集的的結構是一顆樹,它的邊是有向且只指向父節點的。那麼刪除乙個節點(也就是讓它的父節點成為它自己),指向這個節點孩子節點的根就會丟失。學習這個演算法的時候網上說是用虛根,看了很久才看懂。
我就想用通俗更易懂的描述出來」虛根「:
例子:食品店要給顧客甲派送食物food裝在箱子box裡,box有個掛鉤(掛鉤就相當於連線父節點的邊)。food儲存箱子編號,box存父節點。
food有很多,把要送的歸在一類後。顧客甲打**退訂了某些。
如下圖,food[2]=2.編為2的food它的箱子box編號是2
box[3]=3;編號為3的箱子box它的掛鉤掛在自己上(它的父節點是它自己)。
建立如下並查集樹。box[3]=2;
然後顧客甲打**要退訂編號為4,6的food。
接下來我們只需要把編號為4的food拿走,用編號為n++(7)的箱子裝起來。
編號為4的箱子依然留在那裡,這樣就不影響編號4的box後面掛的箱子的根節點就不會喪失。
拿走6同理。
接下來又有一顧客乙要走了4,6.
box[food[6]]=food[4];\\把編號為6的food它所在的箱子8的掛鉤掛到編號為4的food它所在的箱子7上。
food 2,3,1,5歸顧客甲一類,food 4,6歸顧客乙一類。這樣雖然浪費了盒子但是歸類是正確的。搜尋x代表元,也就是通過x的箱子找到根箱子。
下附**:
#include #include int box[1000050];
int food[1000050];
bool mark[1000050];
int find(int x)
return f;
}void merge(int xx,int yy)
int main()
{ int n,m;
char ch;
int x,y;
int ans;
int count=1;
int t;
int i;
while(~scanf("%d%d",&n,&m))
{ t=n;
for(i=0;i
NYOJ 1022 合縱連橫(並查集刪除操作)
合縱連橫 時間限制 1000 ms 記憶體限制 65535 kb 難度 3 描述 亂世天下,諸侯割據。每個諸侯王都有一片自己的領土。但是不是所有的諸侯王都是安分守己的,實力強大的諸侯國會設法吞併那些實力弱的,讓自己的領土面積不斷擴大。而實力弱的諸侯王為了不讓自己的領土被吞併,他會聯合一些其他同樣弱小...
NYOJ1022合縱連橫(支援刪除操作的並查集)
時間限制 1000 ms 記憶體限制 65535 kb 難度 3 描述 亂世天下,諸侯割據。每個諸侯王都有一片自己的領土。但是不是所有的諸侯王都是安分守己的,實力強大的諸侯國會設法吞併那些實力弱的,讓自己的領土面積不斷擴大。而實力弱的諸侯王為了不讓自己的領土被吞併,他會聯合一些其他同樣弱小的諸侯國,...
合縱連橫(並查集)
描述亂世天下,諸侯割據。每個諸侯王都有一片自己的領土。但是不是所有的諸侯王都是安分守己的,實力強大的諸侯國會設法吞併那些實力弱的,讓自己的領土面積不斷擴大。而實力弱的諸侯王為了不讓自己的領土被吞併,他會聯合一些其他同樣弱小的諸侯國,組成聯盟 聯盟不止乙個 來共同抵抗那些強大的諸侯國。強大的諸侯國為了...