求大佬教学
  • 板块P2170 选学霸
  • 楼主lzhh_lzhh
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/12/2 22:15
  • 上次更新2024/12/3 14:20:48
查看原帖
求大佬教学
1051049
lzhh_lzhh楼主2024/12/2 22:15
#include<bits/stdc++.h>
using namespace std;
int n,m,k;
int group[20004];		//group[i]表示i在哪个组
int num[20004];
vector<int> d;		//d[i]表示多少个人实力相当
int dp[2][20004];		//dp[i][j]表示选择i组实力相当的人,人数为j时,与m的误差
//dp[i][j]=min(dp[i-1][j-d[i]],dp[i-1][j]);
int find(int x){
	if(x!=group[x]) return find(group[x]);
	return group[x];
}		//朴实无华并查集
void bing(int a,int b){
	if(group[a]!=group[b]){		//不同组
		group[a]=find(group[a]);
		group[b]=group[a];		//b往a并
	}
	return ;
}
void suan(int n){
	for(int i=1;i<=n;i++) num[group[i]]++;
	for(int i=1;i<=n;i++){
		if(num[i]!=0) d.push_back(num[i]);
	}
	return ;
} 
int main(){
	cin>>n>>m>>k;		//总人数 选择人数 相同人数
	for(int i=1;i<=n;i++) group[i]=i;		//初始化
	for(int i=1;i<=k;i++){
		int a,b;
		cin>>a>>b;
		bing(a,b);
	}		//处理并查集
	/*
	for(int i=1;i<=n;i++){
		if(group[i]!=0) cout<<i<<' '<<group[i]<<endl; 
	}*/
	suan(n);
	dp[0][0]=m;
	for(int i=1;i<=d.size();i++){
		for(int j=1;j<=n;j++){
			dp[i%2][j]=min(abs(dp[(i-1)%2][j-d[i-1]]),abs(dp[(i-1)%2][j]));
			if(dp[i%2][j]==0){
				cout<<m<<endl;
				return 0;
			}
		}
	}
	cout<<m+dp[d.size()%2][n]<<endl;
	return 0;
}
2024/12/2 22:15
加载中...