1. 程式人生 > >BZOJ-1854-[Scoi2010]遊戲(並查集)

BZOJ-1854-[Scoi2010]遊戲(並查集)

isp 樹形結構 scanf for 數據 描述 ++ define day

Description

lxhgww最近迷上了一款遊戲,在遊戲裏,他擁有很多的裝備,每種裝備都有2個屬性,這些屬性的值用[1,10000]之間的數表示。當他使用某種裝備時,他只能使用該裝備的某一個屬性。並且每種裝備最多只能使用一次。 遊戲進行到最後,lxhgww遇到了終極boss,這個終極boss很奇怪,攻擊他的裝備所使用的屬性值必須從1開始連續遞增地攻擊,才能對boss產生傷害。也就是說一開始的時候,lxhgww只能使用某個屬性值為1的裝備攻擊boss,然後只能使用某個屬性值為2的裝備攻擊boss,然後只能使用某個屬性值為3的裝備攻擊boss……以此類推。 現在lxhgww想知道他最多能連續攻擊boss多少次?

Input

輸入的第一行是一個整數N,表示lxhgww擁有N種裝備 接下來N行,是對這N種裝備的描述,每行2個數字,表示第i種裝備的2個屬性值

Output

輸出一行,包括1個數字,表示lxhgww最多能連續攻擊的次數。

Sample Input

3
1 2
3 2
4 5

Sample Output

2

HINT

【數據範圍】
對於30%的數據,保證N < =1000
對於100%的數據,保證N < =1000000

Source

Day1

題解

這道題有巧妙的並查集做法,這裏簡單講一下

我們把武器的屬性當成點,考慮武器屬性之間的連邊

當一個聯通塊是一個樹形結構的時候,假設樹中有x個點,那麽就可以從中取出x-1個點來

當不是樹形結構時,可以從中取出x個點來

我們用並查集來維護

這裏我們用flag[i]表示裝備攻擊為i的是否可以

當find(x)和find(y)不同時,判斷find(x)和find(y)的大小,當兩者都沒有被標記的話,取較小的標記掉,當然如果較小的已經被標記掉了,就把較大的標記

當相同的時候,直接標記即可

最後枚舉直到某個沒有被標記為止

技術分享
 1 #include<bits/stdc++.h>
 2 #define N 1000005
 3 using namespace std;
 4 int n,x,y;
 5 int fa[N];
 6 bool flag[N];
7 int find(int x){ if (x!=fa[x]) fa[x]=find(fa[x]); return fa[x]; } 8 int main(){ 9 scanf("%d",&n); 10 for (int i=1;i<=n+1;i++) fa[i]=i; 11 for (int i=1;i<=n;i++){ 12 scanf("%d%d",&x,&y); 13 int f1=find(x),f2=find(y); 14 if (f1==f2) flag[f1]=true; 15 else{ 16 if (f1>f2) swap(f1,f2); 17 if (flag[f1]) flag[f2]=true; 18 else flag[f1]=true; 19 fa[f1]=f2; 20 } 21 } 22 for (int i=1;i<=n+1;i++) 23 if (!flag[i]){ 24 printf("%d\n",i-1); 25 return 0; 26 } 27 return 0; 28 }
View Code

BZOJ-1854-[Scoi2010]遊戲(並查集)