CODEVS【3372】选学霸

题目描述 Description

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

输入描述 Input Description

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

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

输出描述 Output Description

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

样例输入 Sample Input

4 3 2

1 2

3 4

样例输出 Sample Output

2

数据范围及提示 Data Size & Hint

100%的数据N,P<=30000

实力相当的人要尽量选上,因此我们可以利用并查集把实力相当的人合并,每个集中的老大都有自己的盟友(实力相当的人)(第i个人盟友个数用w[i]表示,初始化w[i]=1),当合并两个集时(f[a]=b),要注意把a的盟友同时合并给b,即w[b]+=w[a],a的盟友自然成了b的盟友,a现在只是一个小喽罗,所以w[a]=0;现在开始枚举w[i]不为0的人,则可以把一个个集看作一个个团队(也可以是单人团队),w[i]表示团队人的个数,++k,最终k表示团队的个数。问题转化为了01背包问题。但是注意此问题要求的是差的绝对值最小的值,所以可以从0开始向两边枚举(枚举dp[m-i]是否等于m-i,dp[m+i]是否等于m+i),第一个枚举到的值输出即可。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<vector>
 6 #include<algorithm>
 7 #include<cstring>
 8 #include<vector>
 9 #include<map>
10 #include<stack>
11 #define maxn 30000+50
12 #define inf 0x7fffffff
13 #define  xiao 1e-9
14 using namespace std;
15 int f[maxn],w[maxn],a[maxn],dp[2*maxn];
16 int find(int x)
17 {
18     if(f[x]==x) return x;
19     else return find(f[x]);
20 }
21 int main()
22 {
23     int n,m,k,b,x;
24     cin>>n>>m>>k;
25     for(int i=1;i<=n;++i){f[i]=i;w[i]=1;}
26     for(int i=1;i<=k;++i)
27       {
28           scanf("%d%d",&x,&b);
29           int fa=find(x),fb=find(b);
30           if(fa!=fb)
31             {
32                  f[x]=b;
33                  w[b]+=w[x];
34                  w[x]=0;
35             }
36       }
37       k=0;
38     for(int i=1;i<=n;++i)
39       {
40           if(w[i]!=0) a[++k]=w[i];
41       }
42     for(int i=1;i<=k;++i)
43       {
44           for(int j=2*m+1;j>=a[i];--j)
45               {
46                   dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
47           }
48       }
49       for(int i=0;i<=m;++i)
50       {
51            if(dp[m-i]==m-i){cout<<m-i;break;}
52            if(dp[m+i]==m+i) {cout<<m+i;break;}
53 }
54   return 0;
55 }
56           

选学霸

时间: 2024-10-12 18:31:18

CODEVS【3372】选学霸的相关文章

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

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

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;

选学霸

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

Codevs 1025 选菜

1025 选菜 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 在小松宿舍楼下的不远处,有PK大学最不错的一个食堂——The Farmer’s Canteen(NM食堂).由于该食堂的菜都很不错,价格也公道,所以很多人都喜欢来这边吃饭.The Farmer’s Canteen的点菜方式如同在超市自选商品一样,人们从一个指定的路口进去,再从一个指定的路口出来并付款.由于来这里就餐的人数比较多,所以人们自觉地在进入口的时候就排

codevs——1008 选数

1008 选数 2002年NOIP全国联赛普及组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 已知 n 个整数 x1,x2,…,xn,以及一个整数 k(k<n).从 n 个整数中任选 k 个整数相加,可分别得到一系列的和.例如当 n=4,k=3,4 个整数分别为 3,7,12,19 时,可得全部的组合与它们的和为: 3+7+12=22 3+7+19=29 7+12+19=38 3+12+19=34. 现在,要求你计算出

CODEVS 1008选数

题目描述 Description 已知 n 个整数 x1,x2,-,xn,以及一个整数 k(k<n).从 n 个整数中任选 k 个整数相加,可分别得到一系列的和.例如当 n=4,k=3,4 个整数分别为 3,7,12,19 时,可得全部的组合与它们的和为: 3+7+12=22 3+7+19=29 7+12+19=38 3+12+19=34. 现在,要求你计算出和为素数共有多少种. 例如上例,只有一种的和为素数:3+7+19=29). 输入描述 Input Description 键盘输入,格式为