选学霸
Posted kanchuang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了选学霸相关的知识,希望对你有一定的参考价值。
题目描述
老师想从N名学生中选M人当学霸,但有K对人实力相当,如果实力相当的人中,一部分被选上,另一部分没有,同学们就会抗议。所以老师想请你帮他求出他该选多少学霸,才能既不让同学们抗议,又与原来的M尽可能接近
输入输出格式
输入格式:
第一行,三个正整数N,M,K。
第2...K行,每行2个数,表示一对实力相当的人的编号(编号为1…N)
输出格式:
一行,表示既不让同学们抗议,又与原来的M尽可能接近的选出学霸的数目。(如果有两种方案与M的差的绝对值相等,选较小的一种:)
输入输出样例
说明
100%的数据N,P<=20000
闲话:
学霸还用选吗,显然是我啊。。。
分析:
本题先用并查集将实力相同的合并,然后再按背包DP做就行了。
CODE:
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 const int M=100005; 8 int n,m,k,fa[M],cnt[M],f[M]; 9 int read() 10 char c=getchar();int ans=0; 11 while (c<‘0‘||c>‘9‘) c=getchar(); 12 while (c>=‘0‘&&c<=‘9‘) ans=(ans<<1)+(ans<<3)+(c^48),c=getchar(); 13 return ans; 14 15 int found(int x) 16 if (fa[x]==x) return x; 17 return fa[x]=found(fa[x]); 18 19 int main() 20 n=read(),m=read(),k=read(); 21 for (int i=1;i<=n;i++) fa[i]=i; 22 for (int i=1,x,y;i<=k;i++) 23 x=read(),y=read(); 24 fa[found(x)]=found(y); 25 26 for (int i=1;i<=n;i++) cnt[found(i)]++; 27 f[0]=1; 28 for (int i=1;i<=n;i++) 29 if (!cnt[i]) continue; 30 for (int j=n;j>=cnt[i];j--) f[j]|=f[j-cnt[i]]; 31 32 int key=1000000,ans=1000000; 33 for (int i=0;i<=n;i++) 34 if (f[i]&&abs(i-m)<ans) ans=abs(i-m),key=i; 35 printf("%d",key); 36 return 0; 37
以上是关于选学霸的主要内容,如果未能解决你的问题,请参考以下文章