题意
解题思路
- 1<=n<=1e5 但 1<=ai,bi<=1e9 ,所以需要把ai、bi共2n个数离散化到2e5
- 用并查集把ai和bi并到一起,统计每个集合的元素个数用ans[]存放
- 每合并一次ai和bi说明该集合中可选个数可+1,用cs[]存放
- 每个集合取min(ans,cs)相加即为答案
代码
#include<stdio.h>
#include<algorithm>
using namespace std;
const int N=2e5+5;
int father[N],a[N],b[N],cs[N],ans[N],vis[N];
int T,n,m;
int Find(int x)
{
if(x!=father[x])father[x]=Find(father[x]);
return father[x];
}
void join(int x,int y)
{
int fx=Find(x),fy=Find(y);
if(fx!=fy)
{
father[fx]=fy;
ans[fy]+=ans[fx];
}
return ;
}
int main()
{
scanf("%d",&T);
for(int k=1;k<=T;k++)
{
for(int i=0;i<N;i++){father[i]=i;cs[i]=0;ans[i]=1;}
scanf("%d",&m);
int x,y,mm=2*m;
for(int i=1;i<=mm;i+=2)
{
scanf("%d%d",&a[i],&a[i+1]);
b[i]=a[i];b[i+1]=a[i+1];
}
sort(b+1,b+1+mm);
int cnt=unique(b+1,b+1+mm)-b-1;
int maxa=-1;
for(int i=1;i<=mm;i+=2)
{
a[i]=lower_bound(b+1,b+1+cnt,a[i])-b;
a[i+1]=lower_bound(b+1,b+1+cnt,a[i+1])-b;
join(a[i],a[i+1]);
maxa=max(maxa,max(a[i],a[i+1]));
}
for(int i=1;i<=mm;i+=2)
{
int fa=Find(a[i]);
cs[fa]++;
}
int maxn=0;
for(int i=1;i<=maxa;i++)
{
vis[i]=0;
int fa=Find(i);
}
for(int i=1;i<=maxa;i++)
{
int fa=Find(i);
if(!vis[fa])
{
maxn+=min(cs[fa],ans[fa]);
vis[fa]=1;
}
}
printf("Case #%d: %d\n",k,maxn);
}
return 0;
}