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

题目传送门:https://www.luogu.org/problem/show?pid=2170

题目描述

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

利用并查集将所有实力相当的人并到一个集合当中,把每个集合看做一个物品,物品的价值为每个集合中的人数,进而转换为01背包问题,由于是使价值总和与m的差的绝对值最小,于是利用2*m容量的背包,dp即可。

状态转移方程:f[j]=max(f[j],f[j-cnt[i]]+cnt[i])。

从m开始向两边扫描寻找答案即可得解。

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 using namespace std;
 5
 6 int n,m,k,tot,que[20050],cnt[20050],father[20050],f[50050];
 7
 8 int gf(int x) {
 9     if (father[x]==x) return x;
10     father[x]=gf(father[x]);
11     return father[x];
12 }
13
14 int main() {
15     scanf("%d%d%d",&n,&m,&k);
16     for (int i=1; i<=n; i++) father[i]=i;
17     for (int i=1; i<=k; i++) {
18         int x,y;
19         scanf("%d%d",&x,&y);
20         int fx=gf(x);
21         int fy=gf(y);
22         if (fx!=fy) father[fx]=fy;
23     }
24     for (int i=1; i<=n; i++) cnt[gf(i)]++;
25     for (int i=1; i<=n; i++) if (cnt[i]) que[++tot]=i;
26     for (int i=1; i<=tot; i++) {
27         int cur=que[i];
28         for (int j=2*m; j>=cnt[cur]; j--)
29             f[j]=max(f[j],f[j-cnt[cur]]+cnt[cur]);
30     }
31     for (int i=0; i<=m; i++) {
32         if (f[m-i]==m-i) {
33             printf("%d",m-i);
34             break;
35         }
36         if (f[m+i]==m+i) {
37             printf("%d",m+i);
38             break;
39         }
40     }
41 }
时间: 2024-10-07 05:45:27

[luogu P2170] 选学霸(并查集+dp)的相关文章

poj1417(种类并查集+dp)

题目:http://poj.org/problem?id=1417 题意:输入三个数m, p, q 分别表示接下来的输入行数,天使数目,恶魔数目: 接下来m行输入形如x, y, ch,ch为yes表示x说y是天使,ch为no表示x说y不是天使(x, y为天使,恶魔的编号,1<=x,y<=p+q):天使只说真话,恶魔只说假话: 如果不能确定所有天使的编号,输出no,若能确定,输出所有天使的编号,并且以end结尾: 注意:可能会有连续两行一样的输入:还有,若x==y,x为天使: 思路:种类并查集+

真正的骗子(并查集+dp+dp状态回溯)

[//]: # (推荐题解模板,请替换blablabla等内容 ^^) ### 题目描述 一个岛上存在着两种居民,一种是天神,一种是恶魔. 天神永远都不会说假话,而恶魔永远都不会说真话. 岛上的每一个成员都有一个整数编号(类似于身份证号,用以区分每个成员). 现在你拥有n次提问的机会,但是问题的内容只能是向其中一个居民询问另一个居民是否是天神,请你根据收集的回答判断各个居民的身份. 输入格式 输入包含多组测试用例. 每组测试用例的第一行包含三个非负整数n,p1,p2p1,p2,其中n是你可以提问

poj1417 true liars(并查集 + DP)详解

这个题做了两天了.首先用并查集分类是明白的, 不过判断是否情况唯一刚开始用的是搜索.总是超时. 后来看别人的结题报告, 才恍然大悟判断唯一得用DP. 题目大意: 一共有p1+p2个人,分成两组,一组p1个,一组p2个.给出N个条件,格式如下: x y yes表示x和y分到同一组 x y no表示x和y分到不同组 问分组情况是否唯一,若唯一则按从小到大顺序输出,否则输出no.保证不存在矛盾条件,但是有可能出现x=y的情况. 题目分析: 题中会给我们一些信息, 告诉我们那些是同一类, 哪些是不同类.

【POJ1417】【带标记并查集+DP】True Liars

Description After having drifted about in a small boat for a couple of days, Akira Crusoe Maeda was finally cast ashore on a foggy island. Though he was exhausted and despaired, he was still fortunate to remember a legend of the foggy island, which h

POJ 1417 True Liars(并查集+DP)

大意: 一个岛上有神与恶魔两个种族,神会说真话,恶魔会说假话.已知神与恶魔的个数,但不知道具体个人是属于哪个. n,x,y 这个人问n次 ,x为神的个数,y为恶魔的个数. 每次的问题为 xi,yi,a 问xi ,yi是否为神? a为yes/no.注意xi,yi可能为同一个人 若最终可得出哪些是神则从小到大输出神的编号,并最终输出end 否则输出no 思路: 经过简单推理可得,只要是说yes,xi,yi为同一个族,no则不为同一个族. 这样通过使用并查集+relation(relation[i]为

poj 1417 并查集+dp

转自:点我 题目:给出p1+p2个人,其中p1个是好人,p2个是坏人.然后有一些关系 ,a说b是好人(坏人).其中没有矛盾的,判断是否有唯一解判断哪些人是好人,哪些人是坏人. 其中比较重要的是,好人总说真话,坏人总说假话.不需要判断矛盾.唯一解 http://poj.org/problem?id=1417 其中好人说真话,坏人说假话这点很重要. 那么如果一个人说另一个人是好人,那么如果这个人是好人,说明 对方确实是好人,如果这个是坏人,说明这句话是假的,对方也是坏人. 如果一个人说另一个人是坏人

hdu 2144 Evolution(并查集+dp)

先预处理一下数据..类似求LCS 然后并查集 1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<string> 6 #include<queue> 7 #include<algorithm> 8 #include<map> 9 #include<iomanip> 10

Luogu P3295 [SCOI2016]萌萌哒(并查集+倍增)

P3295 [SCOI2016]萌萌哒 题面 题目描述 一个长度为 \(n\) 的大数,用 \(S_1S_2S_3 \cdots S_n\) 表示,其中 \(S_i\) 表示数的第 \(i\) 位, \(S_1\) 是数的最高位.告诉你一些限制条件,每个条件表示为四个数, \(l_1,r_1,l_2,r_2\) ,即两个长度相同的区间,表示子串 \(S_{l_1}S_{l_1+1}S_{l_1+2} \cdots S_{r_1}\) 与 \(S_{l_2}S_{l_2+1}S_{l_2+2} \

[Tarjan][并查集][dp] Jzoj P4253 QYQ在艾泽拉斯

Description 在艾泽拉斯的无尽之海里,有着一群不为人知的由各个种族的冒险者统治的岛屿,这些岛屿都很庞大,足以在上面建造许多的城市,城市之间有一些单向道路连接.有一天,QYQ无意中发现了这些岛屿,并且发现在每个城市的地下都或多或少埋藏着一些装备.金币.宝物……可是正当QYQ兴奋不已打算全部把它们拿走时,他却惊奇的发现你的魔法在这里被限制住了,唯一可用的技能就是闪现,而且魔法只够他使用K次这个技能了,每次使用这个技能QYQ只能从一个岛屿上闪现到另外一个岛屿上.每一个岛屿只能登上一次,QYQ