Final Dash
冰茶姬+背包
题目
传送门:选学霸
考察要点:01背包、并查集
做法
首先把实力相同的全都用并查集并起来,把在每个集合的人数记录下来
然后就是背包问题了,注意,要使原来的M尽可能接近的选出学霸的数目,可能选多余m个人,所以把背包容量扩大为2m
代码
using namespace std; #define INF 999999999 const int N=200000+1000; int n,m,op,fat[N],p[N],ans[N],dp[N]; int pans=INF,Mins=INF; int find(int x){ if(fat[x]==x) return x; return fat[x]=find(fat[x]); } int main() { ios::sync_with_stdio(false); cin>>n>>m>>op; for(int i=1; i<=n; i++) fat[i]=i,p[i]=1; for(int i=1; i<=op; i++){ int a,b; cin>>a>>b; int u=find(a),v=find(b); if(u!=v) fat[u]=v,p[v]+=u; } int kk=0; for(int i=1; i<=n; i++) if(fat[i]==i){ kk++; ans[kk]=p[i]; } for(int i=1; i<=kk; i++) for(int k=2*m; k>=ans[i]; k--) dp[k]=max(dp[k],dp[k-ans[i]]+ans[i]); for(int i=1; i<=2*m; i++) if(Mins>abs(dp[i]-m)) Mins=abs(dp[i]-m),pans=dp[i]; if(pans==INF) cout<<0<<endl; else cout<<pans<<endl; return 0; }
|