选学霸

题面

并查集+背包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 }

猜你喜欢

转载自www.cnblogs.com/ainiyuling/p/11162803.html
今日推荐