洛谷P2170 选学(da)霸(lao)

题目:https://www.luogu.org/problemnew/show/P2170

题目描述

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

解析

唉,我并查集都忘得差不多了orz。

如果一些人的实力相同,那么他们中要么全选,要么不选。

这像不像01背包呢?

用并查集处理水平相同的人,如果相同归在一块,看成一个整体。

这个整体的 价值 和 所占用的体积 都为这个整体的人数。

然后就是一个背包dp啦,可以用f[i]表示体积为i能放多少人,如果f[i]==i则代表这种方案合法。

当然也可以采用可行性dp(本文即是),f[i]表示i人能否被取到。

没有得满分的dalao们注意啦:

①你有可能一个人都不选

②不要码错并查集(估计只有我这么。。。。。。)

③计算每一个整体的时候,判断某个属于哪个集体时用find(x)而不是fa[x](见代码)

④没了,祝您ak愉快

代码如下:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<cstdlib> 
 7 using namespace std;
 8 #define maxn 200100
 9 int n,m,k,ra,rb;
10 int fa[maxn];
11 bool f[2*maxn];
12 int groupr[maxn];
13 int group[maxn],tot;
14 int finda(int x){
15     if (fa[x]==x) return fa[x];
16     else return fa[x]=finda(fa[x]);
17 }
18 void unionn(int x,int y){
19     int fx=finda(x),fy=finda(y);
20     if (fx==fy) return;
21     fa[fx]=fy;
22 }
23 int main(){
24     scanf("%d%d%d",&n,&m,&k);
25     for (int i=1;i<=n;++i) fa[i]=i;
26     for (int i=1;i<=k;++i){
27         scanf("%d%d",&ra,&rb);
28         //if (ra>rb) swap(ra,rb); 
29         unionn(ra,rb);
30     }
31     for (int i=1;i<=n;++i){
32         groupr[finda(i)]++; //不要写成fa[i]
33     }
34     for (int i=1;i<=n;++i){
35         if (groupr[i]){
36             group[++tot]=groupr[i];
37         }
38     }
39     f[0]=true;
40     for (int i=1;i<=tot;++i){
41         for (int j=2*m;j>=group[i];--j){
42             if (f[j-group[i]]){
43                 f[j]=true;
44             }
45         }
46     }
47     for (int i=0;i<=m;++i){
48         if (f[m-i]){
49             printf("%d",m-i);
50             return 0;
51         }
52         if (f[m+i]){
53             printf("%d",m+i);
54             return 0;
55         }
56     } 
57     return 0;
58 }
View Code
原文地址:https://www.cnblogs.com/gjc1124646822/p/7795483.html