1. 程式人生 > >BZOJ 1854: [Scoi2010]遊戲 【二分圖】【並查集】

BZOJ 1854: [Scoi2010]遊戲 【二分圖】【並查集】

Description

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

題解

容易得到,只要p個點構成了一棵樹,那麼一定能夠滿足其中任意p1個點,如果p個點構成了一個環,那麼一定所有的點都能夠滿足。只要用並查集判斷一下就可以了。

程式碼

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 10006
using namespace std;
inline char nc(){
    static char buf[100000],*i=buf,*j=buf;
    return i==j&&(j=(i=buf)+fread(buf,1
,100000,stdin),i==j)?EOF:*i++; } inline int _read(){ char ch=nc();int sum=0; while(!(ch>='0'&&ch<='9'))ch=nc(); while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc(); return sum; } int n,fa[maxn]; bool vis[maxn]; int get(int x){return fa[x]==x?x:get(fa[x]);} int main(){ n=_read(); for
(int i=1;i<=10000;i++)fa[i]=i; for(int i=1;i<=n;i++){ int x=_read(),y=_read(); x=get(x);y=get(y); if(x>y)swap(x,y); fa[x]=y;vis[x]=1; } for(int i=1;i<=10000;i++) if(!vis[i])return printf("%d\n",i-1),0; return printf("10000\n"),0; }