选学霸

题目描述

老师想从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 }

原文地址:https://www.cnblogs.com/kanchuang/p/11150471.html

时间: 2024-10-12 20:43:17

选学霸的相关文章

CODEVS【3372】选学霸

题目描述 Description 老师想从N名学生中选M人当学霸,但有K对人实力相当,如果实力相当的人中,一部分被选上,另一部分没有,同学们就会抗议.所以老师想请你帮他求出他该选多少学霸,才能既不让同学们抗议,又与原来的M尽可能接近. 输入描述 Input Description 第一行,三个正整数N,M,K. 第2...K行,每行2个数,表示一对实力相当的人的编号(编号为1…N). 输出描述 Output Description 一行,表示既不让同学们抗议,又与原来的M尽可能接近的选出学霸的数

3372 选学霸

3372 选学霸 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 题目描述 Description 老师想从N名学生中选M人当学霸,但有K对人实力相当,如果实力相当的人中,一部分被选上,另一部分没有,同学们就会抗议.所以老师想请你帮他求出他该选多少学霸,才能既不让同学们抗议,又与原来的M尽可能接近. 输入描述 Input Description 第一行,三个正整数N,M,K. 第2...K行,每行2个数,表示一对实力相当的人的编号(编号为1…N). 输

【洛谷P2170】选学霸

题目描述 老师想从N名学生中选M人当学霸,但有K对人实力相当,如果实力相当的人中,一部分被选上,另一部分没有,同学们就会抗议.所以老师想请你帮他求出他该选多少学霸,才能既不让同学们抗议,又与原来的M尽可能接近 输入输出格式 输入格式: 第一行,三个正整数N,M,K. 第2...K行,每行2个数,表示一对实力相当的人的编号(编号为1-N) 输出格式: 一行,表示既不让同学们抗议,又与原来的M尽可能接近的选出学霸的数目.(如果有两种方案与M的差的绝对值相等,选较小的一种:) 输入输出样例 输入样例#

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

题目传送门:https://www.luogu.org/problem/show?pid=2170 题目描述 老师想从N名学生中选M人当学霸,但有K对人实力相当,如果实力相当的人中,一部分被选上,另一部分没有,同学们就会抗议.所以老师想请你帮他求出他该选多少学霸,才能既不让同学们抗议,又与原来的M尽可能接近 输入输出格式 输入格式: 第一行,三个正整数N,M,K. 第2...K行,每行2个数,表示一对实力相当的人的编号(编号为1-N) 输出格式: 一行,表示既不让同学们抗议,又与原来的M尽可能接

CODEVS3372 选学霸 (easy)

题目描述 Description 老师想从N名学生中选M人当学霸,但有K对人实力相当,如果实力相当的人中,一部分被选上,另一部分没有,同学们就会抗议.所以老师想请你帮他求出他该选多少学霸,才能既不让同学们抗议,又与原来的M尽可能接近. 思路:将实力相当的人都并到一个集合中,统计出集合中元素的个数.然后做一个类似01背包(布尔型)的东西,找到最优解就可以了. code: #include<cstdio> #include<iostream> using namespace std;

codevs 3372 选学霸(hash+并查集+多重背包)

先通过并查集处理出来有多少种不同的集合,每个集合有多少人.一定要不要忘记了与别的没有联系的独立点. 并查集的时候可以通过hash处理出来每个数目相同的集合的个数. 这样以人数为权值,个数为限制进行多重背包,结果就是答案. 题目链接:http://codevs.cn/problem/3372/ #include <algorithm> #include <iostream> #include <stdlib.h> #include <string.h> #in

[Luogu] 选学霸

https://www.luogu.org/problemnew/show/P2170 并查集+DP #include <iostream> #include <cstring> #include <cmath> using namespace std; const int maxn=20005; int n,m,k,tot; int p[maxn]; int man[maxn]; int f[maxn+maxn]; int find(int x) { return (

CONTEST45 呵呵呵呵呵

题目质量差评!为什么不给数据范围! A.乘积最大3 题目:http://dev.luogu.org/problem/show?pid=2172 题解:sb题,均值定理. 代码: 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #include<iostream> 7 #include

【日常学习】清明前后两周学练总结

要写关键路径,发现图论早已忘得一塌糊涂,悲哀之余,抓紧复习.翻高级本时又看见了前面的贪心,于是就又把贪心练了一下.写了几道比较老的题目,像是积木大赛.之后还突发奇想练了栈一类的.总之,这两周的练习相当凌乱.下面贴一下近期做过的几道题目吧. 表达式求值专项训练 codevs1750 加法表达式 (自带吐槽:直接用读入优化那样的getchar()读入 但是要注意读不了的时候返回值是-1 所以不能用"!" 另外最后一次读不下去要break直接加上) codevs2715 表达式运算 (自带吐