91pts求调
  • 板块P2170 选学霸
  • 楼主sunyizhe还是MC大佬
  • 当前回复2
  • 已保存回复2
  • 发布时间2022/12/20 11:53
  • 上次更新2023/10/24 07:08:34
查看原帖
91pts求调
481330
sunyizhe还是MC大佬楼主2022/12/20 11:53

语言:C++14(GCC9) O2

这里把题目中的 kk 换成了 cc

//程序算法:并查集,01背包,DP 
#include <bits/stdc++.h>
using namespace std;
const int N=20010;
int p[N],rk[N],cnt[N],d[N];//c[]:并查集元素个数    d[]:DP数组 
int n,m,c;
inline void make_set(int x)
{
	p[x]=x;
	rk[x]=cnt[x]=1;
} 
int find(int x)
{
	if(p[x]!=x)p[x]=find(p[x]);
	return p[x];
}
int union_set(int x,int y)
{
	if(x!=y)
	{
		x=find(x),y=find(y);
		if(rk[x]<rk[y])swap(x,y);
		p[y]=x,cnt[x]+=cnt[y];
		if(rk[x]==rk[y])rk[x]++;
	}
	return x;
} 
int main()
{
	scanf("%d %d %d",&n,&m,&c);
	if(c==0&&n>=m)
	{
		printf("%d\n",m);
		return 0;
	}
	for(int i=1;i<=n;i++)make_set(i);
	for(int i=1;i<=c;i++)
	{
		int x,y;
		scanf("%d %d",&x,&y);
		union_set(x,y);
	}//并查集基本操作 
	for(int i=1;i<=n;i++)//01背包模板
	{
		if(find(i)!=i)continue;
		for(int j=n;j>=cnt[i];j--)
			d[j]=max(d[j],d[j-cnt[i]]+cnt[i]);
	}
	int ans,minm=0x3f3f3f3f;
	for(int i=0;i<=n;i++)//判断最接近m的人数 
		if(abs(d[i]-m)<minm)minm=abs(d[i]-m),ans=d[i];
	printf("%d\n",ans);
	return 0;
}
2022/12/20 11:53
加载中...