https://cn.vjudge.net/problem/615831/origin

题意

n个人;  计划是每个人都拿一个礼物来送给一个除了自己之外的人;  如果一个人没有送出礼物,那么它和它送礼物的对象都得不到礼物;  但是已经知道有k个人会忘记带礼物来;  问最少有几个人收不到礼物,最多有多少个人收不到礼物

既然是求点和点之间的关系,首先会想到建图,建完图发现事实上图是一个个环状联通快组成的,我们首先对最大值最小值分开进行讨论

最大值:当环是偶数的时候,一个人不送礼物可以提供2个贡献,形成len / 2的贡献,当环是奇数的时候,落单的那一个人需要多一个k去弥补。

所以我们可以贪心的考虑首先将所有人两两配对,每一对用1个花费产生2的贡献,然后在考虑落单的人用1个花费产生1的贡献。

最小值:经过分析可以发现,对于一个环,如果上面有人不送礼物,也就是如果开了这个环,开环的是花费1产生2,之后所有的操作是花费1产生1,如果一个环上的人全部不送礼物,开环产生的多出来的1的贡献可以被消除,所以我们贪心的想到一个环全部扫完了之后再考虑下一个人,如果这个环可以开完,是花费len产生len,如果开不完,是花费len产生len + 1,所以如果K正好可以开满一部分的环,答案就是K,否则答案为K + 1

这就变成了一个多重背包问题,二进制优化一下就可以过了

#include <map>
#include <set>
#include <ctime>
#include <bitset>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
const double eps = 1e-;
const int maxn = 1e6 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,tmp,K;
int tree[maxn];
int SIZE[maxn];
int a[maxn];
void init(){
For(i,,N) tree[i] = i,SIZE[i] = ;
}
int find(int t){
if(t == tree[t]) return t;
return t = find(tree[t]);
}
void Union(int a,int b){
a = find(a); b = find(b);
if(a == b) return;
tree[a] = b;
SIZE[b] += SIZE[a];
}
vector<int>bag;
vector<int>W;
int num[maxn];
bool dp[maxn];
int main()
{
Sca2(N,K);
init();
For(i,,N){
Sca(a[i]);
Union(i,a[i]);
}
For(i,,N) if(tree[i] == i) bag.pb(SIZE[i]);
int cnt = ,tot = ;
for(int i = ; i < bag.size(); i++){
if(bag[i] % ){
cnt++;
tot += bag[i] / ;
}else{
tot += bag[i] / ;
}
}
int MIN,MAX;
if(K <= tot) MAX = K * ;
else MAX = tot * + min(cnt,K - tot);
for(int i = ; i < bag.size(); i ++){
num[bag[i]]++;
}
for(int i = ; i < maxn; i ++){
int k = ;
while(num[i] >= k){
W.pb(i * k);
num[i] -= k;
k <<= ;
}
if(num[i]){
W.pb(i * num[i]);
}
}
dp[] = ;
for(int i = ; i < W.size(); i ++){
int t = W[i];
for(int j = K; j >= t ;j --){
if(dp[j - t]) dp[j] = ;
}
}
if(dp[K]) MIN = K;
else MIN = K + ;
printf("%d %d",MIN,MAX);
#ifdef VSCode
system("pause");
#endif
return ;
}

CodeForces755F 贪心 + 多重背包二进制优化的更多相关文章

  1. hdu1059 dp(多重背包二进制优化)

    hdu1059 题意,现在有价值为1.2.3.4.5.6的石头若干块,块数已知,问能否将这些石头分成两堆,且两堆价值相等. 很显然,愚蠢的我一开始并想不到什么多重背包二进制优化```因为我连听都没有听 ...

  2. HDOJ(HDU).2844 Coins (DP 多重背包+二进制优化)

    HDOJ(HDU).2844 Coins (DP 多重背包+二进制优化) 题意分析 先把每种硬币按照二进制拆分好,然后做01背包即可.需要注意的是本题只需要求解可以凑出几种金钱的价格,而不需要输出种数 ...

  3. HDOJ(HDU).1059 Dividing(DP 多重背包+二进制优化)

    HDOJ(HDU).1059 Dividing(DP 多重背包+二进制优化) 题意分析 给出一系列的石头的数量,然后问石头能否被平分成为价值相等的2份.首先可以确定的是如果石头的价值总和为奇数的话,那 ...

  4. HDOJ(HDU).2191. 悼念512汶川大地震遇难同胞――珍惜现在,感恩生活 (DP 多重背包+二进制优化)

    HDOJ(HDU).2191. 悼念512汶川大地震遇难同胞――珍惜现在,感恩生活 (DP 多重背包+二进制优化) 题意分析 首先C表示测试数据的组数,然后给出经费的金额和大米的种类.接着是每袋大米的 ...

  5. hdu 1171 Big Event in HDU(多重背包+二进制优化)

    题目链接:hdu1171 思路:将多重背包转为成完全背包和01背包问题,转化为01背包是用二进制思想,即件数amount用分解成若干个件数的集合,这里面数字可以组合成任意小于等于amount的件数 比 ...

  6. hdu 2191 (多重背包+二进制优化)

    Problem Description 急!灾区的食物依然短缺!为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品, ...

  7. Coins(多重背包+二进制优化)

    Problem Description Whuacmers use coins.They have coins of value A1,A2,A3...An Silverland dollar. On ...

  8. Cash Machine POJ - 1276 多重背包二进制优化

    题意:多重背包模型  n种物品 每个m个  问背包容量下最多拿多少 这里要用二进制优化不然会超时 #include<iostream> #include<cstdio> #in ...

  9. BZOJ.3425.[POI2013]Polarization(DP 多重背包 二进制优化)

    BZOJ 洛谷 最小可到达点对数自然是把一条路径上的边不断反向,也就是黑白染色后都由黑点指向白点.这样答案就是\(n-1\). 最大可到达点对数,容易想到找一个点\(a\),然后将其子树分为两部分\( ...

随机推荐

  1. Django RBAC用户权限设计方案

    RBAC基于用户权限系统设置方案 RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联.简单地说,一个用户拥有若干角色,每一个角色拥有若干 ...

  2. Codeforces1063D Candies for Children 【分类讨论】【暴力】

    题目分析: 首先要想两个暴力,一个的时间复杂度是$O(n^2)$,另一个是$O([\frac{n}{k}])$的. $n^2$的暴力可以枚举两段,一段有$i$个取两个的小朋友,一段有$j$个取两个的小 ...

  3. Hibernate结合JPA05

    一. JPA简介 JPA是Java Persistence API的简称,中文名Java持久层Api,是JDK1.5注解或者Xml描述对象-关系表的映射关系,并将运行期的实体类对象持久化Dao数据库中 ...

  4. 基于FPGA的UART协议实现(通过线性序列机)

    //////////////////2018/10/15 更新源代码: 实现uart这东西其实早就写了,不过不太完善,对于一个完美主义者来说,必须解决掉它. 1.什么是UART?        通用异 ...

  5. Ionic3 新增 Service

    service是单例模式的 新增Service类 search.service.ts import {Injectable} from '@angular/core'; @Injectable() e ...

  6. Java8的Stream语法详解(转载)

    1. Stream初体验 我们先来看看Java里面是怎么定义Stream的: A sequence of elements supporting sequential and parallel agg ...

  7. AMH 软件目录介绍

    AMH系统shell脚本目录:/root/amh系统所有shell脚本文件目录,不可删除. 网站运行工作根目录:/home/wwwroot面板程序与新建虚拟主机网站都存放于此目录. 其中:/home/ ...

  8. HDOJ 5666//快速积,推公式

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5666 题意:给一条直线x+y=q,在(0,0)往x+y=q上面的整数点连线,x+y=q与x,y轴截成的三角 ...

  9. Jeesite 代码生成

    1.mysql数据库建表 参考自带的sys_area 的创表SQL复制来修修改改即可 2.配置代码生成文件覆盖路径 打开eclipse 按ctrl+shift+R  找到jeesite.propert ...

  10. python3 fileinput模块

    模块fileinput可以对一个或多个文件的内容所有行进行迭代.遍历等操作: 常用方法: fileinput.input(files=None, inplace=False, backup='', b ...