标签:ret problem 说明 wap 二分图 efault 现在 属性 c++
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最多能连续攻击的次数。
3 1 2 3 2 4 5
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 }
都很好写,但是并查集不太好理解。
标签:ret problem 说明 wap 二分图 efault 现在 属性 c++
原文地址:https://www.cnblogs.com/DZN2004/p/12826015.html