Description
一年一度的西科拔河比赛要到了,比赛要求每只队伍的人数不超过cc人。qwy希望从ACM集训队选择尽可能多的人组成一支队伍去参加比赛。
众所周知,ACM集训队人数众多,每个队员不一定认识其他所有队员。程序猿是一种群居动物,他们不希望和不认识的人一起活动(如果A认识B,B认识C,那么可以认为A认识C)。如果A不认识B,那么A和B都不希望和对方组队参赛,并且程序猿希望和所有他认识的人一起参赛。集训队现在有nn个程序猿,编号1−n1−n。qwy现在有一张关系表,表上有mm条关系,每条关系包含两个整数XiXi和YiYi,表示XiXi和YiYi认识。现在qwy想知道,在每个人数限制cc下,他能派出的人数最多的队伍的信息,即队伍的人数和队长(队中编号最大的程序猿)编号。
Input
Output
对每个询问c,输出一行。 如果没有队伍可以选择输出-1。 如果有选择,输出最优选择下的队伍信息,即队伍人数和队伍中队长的编号。 如果有多个选择,输出队长编号最大的那个队伍的信息。
6 3 4 1 3 3 2 5 6 0 1 2 3
-1 1 4 2 6 3 3
Hint
对于第一个样例,只能分为三个队伍:{1,2,3},{4},{5,6}. 第一个询问0,qwy并不能找到一支队伍,人数小于等于0,所以输出-1。 第二个询问1,只能找到{4}这个队伍,队伍信息为(1,4)即1个人,其中队长编号为4。 第三个询问2,输出队伍{5,6}的信息。 第四个询问3。输出队伍{1,2,3}的信息。
PS:这是一个典型的并查集的题,但是因为询问次数很多,所以要预处理,或者后面用二分查找找答案。下面给出两种代码:
结构体保存+二分查找:
#include <iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#include<stack>
#include<string>
const int maxn=2e5+10;
const int mod=1e9+7;
const int inf=1e8;
#define me(a,b) memset(a,b,sizeof(a))
typedef long long ll;
using namespace std;
struct node
{
int x,i;
bool friend operator<(node a,node b)
{
if(a.x==b.x)
return a.i<b.i;
return a.x<b.x;
}
}a[maxn];
int root[maxn];
int find(int x)
{
if(x==root[x])
return x;
return root[x]=find(root[x]);
}
void un(int x,int y)
{
int x1=find(x),y1=find(y);
if(x1!=y1)
root[min(x1,y1)]=max(x1,y1);
}
int er(int l,int r,int c)
{
int mid;
while(l<=r)
{
mid=(l+r)>>1;
if(a[mid].x<=c&&a[mid+1].x>c)
break;
if(a[mid].x>c)
r=mid-1;
else
l=mid+1;
}
return mid;
}
int main()
{
int m,n,q;
cin>>n>>m>>q;
for(int i=1;i<=n;i++)
root[i]=i;
for(int i=0;i<m;i++)
{
int x,y;scanf("%d%d",&x,&y);
un(x,y);
}
me(a,0);
for(int i=1;i<=n;i++)
{
a[find(i)].x++;
a[find(i)].i=find(i);
}
sort(a+1,a+n+1);
while(q--)
{
int c;scanf("%d",&c);
int x=er(1,n,c);
if(!a[x].x||a[x].x>c)
printf("-1\n");
else
printf("%d %d\n",a[x].x,a[x].i);
}
return 0;
}
map记录+lower_bound
#include <iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#include<stack>
#include<string>
const int maxn=2e5+10;
const int mod=1e9+7;
const int inf=1e8;
#define me(a,b) memset(a,b,sizeof(a))
typedef long long ll;
using namespace std;
int root[maxn],pos[maxn],val[maxn];
void inct(int n)
{
for(int i=1;i<=n;i++)
root[i]=i,val[i]=1;
}
int find(int x)
{
if(x==root[x])
return x;
return root[x]=find(root[x]);
}
void un(int x,int y)
{
int x1=find(x),y1=find(y);
if(x1!=y1)
{
root[min(x1,y1)]=max(x1,y1);
val[max(x1,y1)]+=val[min(x1,y1)];
}
}
int main()
{
int m,n,q;
cin>>n>>m>>q;
inct(n);
for(int i=0;i<m;i++)
{
int x,y;scanf("%d%d",&x,&y);
un(x,y);
}
map<int,int>s;
int l=0;
for(int i=1;i<=n;i++)
{
if(root[i]==i)
{
pos[l++]=val[i];
s[val[i]]=i;
}
}
sort(pos,pos+l);
while(q--)
{
int c;scanf("%d",&c);
int x=lower_bound(pos,pos+l,c)-pos;
if(pos[x]==c)
printf("%d %d\n",pos[x],s[pos[x]]);
else if(x<1)
printf("-1\n");
else
printf("%d %d\n",pos[x-1],s[pos[x-1]]);
}
return 0;
}