bzoj1854 [Scoi2010]游戏

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

 

正解:并查集。

开始我想了好久,这题会不会是二分图最大独立集,然后做不出来。然后我就把边连了一下,发现就做完了。。

我们把属性值看成点,把每个武器看成一条边。我们可以发现,一个连通块如果是一个环的话,那么所有点都是可以用的。如果一个连通块不是环,那么有$n-1$个点都是可用的。那么我们连边时就可以直接用并查集。如果当前两个点不在一个连通块,那么把这两个连通块中祖先小的那个并到祖先大的那个块上,并且把小的那个祖先标记一下,表示可以用,如果小的祖先已经标记过,那么我们直接标记大的祖先就行了;否则我们就直接标记这个块的祖先就行了。

 

 1 //It is made by wfj_2048~
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <complex>
 5 #include <cstring>
 6 #include <cstdlib>
 7 #include <cstdio>
 8 #include <vector>
 9 #include <cmath>
10 #include <queue>
11 #include <stack>
12 #include <map>
13 #include <set>
14 #define inf (1<<30)
15 #define il inline
16 #define RG register
17 #define ll long long
18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
19 
20 using namespace std;
21 
22 int fa[10010],vis[10010],n;
23 
24 il int gi(){
25     RG int x=0,q=1; RG char ch=getchar();
26     while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
27     if (ch=='-') q=-1,ch=getchar();
28     while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
29     return q*x;
30 }
31 
32 il int find(RG int x){ return fa[x]==x ? x : fa[x]=find(fa[x]); }
33 
34 il void work(){
35     n=gi(); RG int u,v,x,y;
36     for (RG int i=1;i<=10000;++i) fa[i]=i;
37     for (RG int i=1;i<=n;++i){
38         u=gi(),v=gi();
39     x=find(u),y=find(v);
40     if (x==y) vis[x]=1;
41     else{
42         if (x>y) swap(x,y);
43         if (!vis[x]) vis[x]=1;
44         else vis[y]=1; fa[x]=y;
45     }
46     }
47     for (RG int i=1;i<=10001;++i)
48     if (!vis[i]){ printf("%d\n",i-1); break; }
49     return;
50 }
51 
52 int main(){
53     File("game");
54     work();
55     return 0;
56 }

 

posted @ 2017-04-10 14:24  wfj_2048  阅读(386)  评论(0编辑  收藏  举报