选学霸

Posted kanchuang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了选学霸相关的知识,希望对你有一定的参考价值。

题目描述

老师想从N名学生中选M人当学霸,但有K对人实力相当,如果实力相当的人中,一部分被选上,另一部分没有,同学们就会抗议。所以老师想请你帮他求出他该选多少学霸,才能既不让同学们抗议,又与原来的M尽可能接近

输入输出格式

输入格式:

第一行,三个正整数N,M,K。

第2...K行,每行2个数,表示一对实力相当的人的编号(编号为1…N)

输出格式:

一行,表示既不让同学们抗议,又与原来的M尽可能接近的选出学霸的数目。(如果有两种方案与M的差的绝对值相等,选较小的一种:)

输入输出样例

输入样例#1:
4 3 2
1 2
3 4
输出样例#1: 
2

说明

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 

 

以上是关于选学霸的主要内容,如果未能解决你的问题,请参考以下文章

洛谷P2170选学霸

[luogu P2170] 选学霸(并查集+dp)

600多种编程语言为何选学Python?这几个理由足够了!

总目录(13章必修,2章选修)

什么百度霸屏?百度霸屏是什么意思?

求数学学霸解。。。。