连续攻击游戏题解

Posted dzn2004

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了连续攻击游戏题解相关的知识,希望对你有一定的参考价值。

P1640 [SCOI2010]连续攻击游戏

题目描述

lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示。当他使用某种装备时,他只能使用该装备的某一个属性。并且每种装备最多只能使用一次。游戏进行到最后,lxhgww遇到了终极boss,这个终极boss很奇怪,攻击他的装备所使用的属性值必须从1开始连续递增地攻击,才能对boss产生伤害。也就是说一开始的时候,lxhgww只能使用某个属性值为1的装备攻击boss,然后只能使用某个属性值为2的装备攻击boss,然后只能使用某个属性值为3的装备攻击boss……以此类推。现在lxhgww想知道他最多能连续攻击boss多少次?

输入格式

输入的第一行是一个整数N,表示lxhgww拥有N种装备接下来N行,是对这N种装备的描述,每行2个数字,表示第i种装备的2个属性值

输出格式

输出一行,包括1个数字,表示lxhgww最多能连续攻击的次数。

输入输出样例

输入 #1
3
1 2
3 2
4 5
输出 #1
2

说明/提示

Limitation

对于30%的数据,保证N < =1000

对于100%的数据,保证N < =1000000

 

这道题网上说用二分图,也有的人说用并查集

其实不管7用啥答题思路都是一样的。

所以我今天给大家讲一种更简单的方法。

——————————————————————————————————————————————————————————————

对于每一个点对,使得p[i].a<p[i].b

那么对于每一个点对排序,a为第一关键字,b为第二关键字

对于每一个p[i].a,判断是否出现

未出现就标记

出现了就标记p[i].b

最后扫1到Max第一个没有出现过的点

复杂度O(nlogn)

——————————————————————————————————————————————————————————————

其实这种方法就是并查集做法的核心思想。

大家看一下代码应该就明白了。

 1 #include<bits/stdc++.h>
 2 #define rg register
 3 #define N 1000001
 4 using namespace std;
 5 int n,Max,vis[N];
 6 struct T{
 7     int a,b;
 8 }e[N];
 9 bool operator<(T a,T b){
10     if(a.a==a.b)return a.b>b.b;
11     return a.a<b.a;
12 }
13 int main(){
14     freopen("s.in","r",stdin);
15     scanf("%d",&n);
16     for(rg int i=1;i<=n;++i){
17         scanf("%d %d",&e[i].a,&e[i].b);
18         if(e[i].a>e[i].b)swap(e[i].a,e[i].b);
19         Max=max(Max,e[i].b);
20     }
21     sort(e+1,e+n+1);
22     for(rg int i=1;i<=n;++i){
23         if(!vis[e[i].a])vis[e[i].a]=1;
24         else vis[e[i].b]=1;
25     }
26     for(rg int i=1;i<=Max;++i){
27         if(!vis[i]){
28             printf("%d",i-1);
29             return 0;
30         }
31     }
32     printf("%d",Max);
33     return 0;
34 }

下面是并查集的代码:

 1 #include <algorithm>
 2 #include <cstdio>
 3 using namespace std;
 4 int fa[1100000],cir[1100000],num[1100000];
 5 int ans=0;
 6 int get(int t){
 7     if (fa[t]==t) return t;
 8     else {
 9         fa[t]=get(fa[t]);return fa[t];
10     }
11 }
12 int main(){
13     //freopen("a.in","r",stdin);
14        int n;scanf("%d",&n);
15     for (int i=1; i<=n+1; i++) fa[i]=i;
16     for (int i=1; i<=n+1; i++) num[i]=1;
17     for (int i=1; i<=n; i++){
18         int a, b;scanf("%d%d",&a,&b);
19         int ap=get(a), bp=get(b);
20         if (ap==bp)cir[ap]=1;
21         else {
22             cir[ap]=cir[ap]|cir[bp];cir[bp]=0;
23             num[ap]+=num[bp];num[bp]=0;
24             fa[bp]=ap;
25         }
26     }
27     for (int i=1;i<=n+1;i++)
28         if (!cir[get(i)]){
29             if(num[get(i)]==1){ans=i-1;break;}
30             else num[get(i)]--;
31         }
32     printf("%d",ans);
33     return 0;
34 }

 

都很好写,但是并查集不太好理解。

 

 

 

以上是关于连续攻击游戏题解的主要内容,如果未能解决你的问题,请参考以下文章

暑假D14 [SCOI2010]连续攻击游戏(二分图)

「SCOI2010」连续攻击游戏

[SCOI2010]连续攻击游戏

2G 连续攻击游戏

洛谷——P1640 [SCOI2010]连续攻击游戏

[SCOI2010]连续攻击游戏