BZOJ-1854 [Scoi2010]游戏(并查集)
题目描述
\(n(n\leq 10^6)\) 个装备,每个装备都有 \(2\) 个属性,这些属性的值用 \([1,10000]\) 之间的数表示。只能使用装备的某一个属性,每种装备最多只能使用一次。 所使用的属性值必须从 \(1\) 开始连续递增地攻击。求最多能连续攻击多少次?
分析
把每个武器的两个属性看成点,之间连边,让属性值大的作为父亲节点。每次读入一对点,如果两点的祖先相同说明形成了一个环,假设环的编号为 \(1\) ~ \(x\),则 \(x\) 个点可以全选择;如果没有两点祖先相同,说明形成了一条链,可以选择点 \(1\) ~ 点 \(x-1\)(编号最大的点不选)。在并查集每次合并的时候,将祖先编号小的合并到祖先编号大的,同时用 \(vis[i]\) 标记两点中编号小的点 \(i\) 可以到达,假设主函数中第一个无法到达的点为 \(x\),答案即为 $x-1 $。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e4;
int fa[N+10];
int get(int x)
{
if(x==fa[x])
return x;
return fa[x]=get(fa[x]);
}
bool vis[N+10];
int main()
{
int n;
cin>>n;
for(int i=1;i<=N;i++)
fa[i]=i;
for(int i=1;i<=n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
int fx=get(x),fy=get(y);
if(fx!=fy)
{
if(fx>fy)
swap(fx,fy);
fa[fx]=fy;
}
vis[fx]=true;
}
for(int i=1;i<=N+1;i++)
{
if(!vis[i])
{
cout<<i-1<<endl;
break;
}
}
return 0;
}
posted on 2020-12-06 17:52 DestinHistoire 阅读(81) 评论(0) 收藏 举报