并查集+背包dp
1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 using namespace std; 5 int f[100000],p[100000],i,j,x,y,k,m,n,s[100000],dp[100000],tot; 6 int find(int u) 7 { 8 if(f[u]==u) return u; 9 else return f[u]=find(f[u]); 10 } 11 int main() 12 { 13 scanf("%d%d%d",&n,&m,&k); 14 for(i=1;i<=n;i++) 15 f[i]=i,p[i]=1; 16 for(i=1;i<=k;i++) 17 { 18 scanf("%d%d",&x,&y); 19 int u=find(x);int v=find(y); 20 if(u!=v) f[u]=v,p[v]+=p[u]; 21 } 22 for(i=1;i<=n;i++) 23 if(f[i]==i) 24 { 25 tot++; 26 s[tot]=p[i]; 27 } 28 for(i=1;i<=tot;i++) 29 for(j=2*m;j>=s[i];j--) 30 dp[j]=max(dp[j],dp[j-s[i]]+s[i]); 31 int ans=999999999,minn=999999999; 32 for(i=1;i<=2*m;i++) 33 { 34 if(minn>abs(dp[i]-m)) minn=abs(dp[i]-m),ans=dp[i]; 35 } 36 if(ans==999999999) printf("0"); 37 else printf("%d",ans); 38 return 0; 39 }