我用了并查集和0-1背包,但是只有4和5两个测点A了,(程序我看着和题解差不多啊),思路大致写在了程序里,麻烦大佬们帮忙看一下是哪里出了问题,谢谢
//2170
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int fa[20005],r[20005],dp[20005],s[20005];//fa记录父节点,r是以i为代表元素的集合中元素个数,s约等于浓缩版的r()
int n,m,k,x,y,num;//n,m,k含义同原题,num记录集合个数
void init(int n){
for(int i=1;i<=n;i++){
fa[i]=i;
r[i]=1;
}
}
bool cmp(int x,int y){
if(x>y) return true;
else return false;
}
int find(int q){
if(fa[q]==q) return q;
else return fa[q]=find(fa[q]);
}
int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
cin>>n>>m>>k;
for(int i=1;i<=k;i++){
cin>>x>>y;
x=find(x);
y=find(y);
fa[y]=x;
r[x]=r[x]+r[y];
r[y]=0;
}
for(int i=1;i<=n;i++){
if(fa[i]==i){
num++;
s[num]=r[i];
}
}
//接下来是背包
for(int i=1;i<=num;i++)
for(int j=2*m;j>=s[i];j--)
dp[j]=max(dp[j],dp[j-s[i]]+s[i]);
int ans=99999999;
int minn=99999999;
for(int i=1;i<=2*m;i++){
if(minn>abs(dp[i]-m)){
minn=abs(dp[i]-m);
ans=dp[i];
}
}
cout<<ans;
//fclose(sdtin);fclose(stdout);
return 0;
}