CodeForces755F 贪心 + 多重背包二进制优化
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 贪心 + 多重背包二进制优化的更多相关文章
- hdu1059 dp(多重背包二进制优化)
hdu1059 题意,现在有价值为1.2.3.4.5.6的石头若干块,块数已知,问能否将这些石头分成两堆,且两堆价值相等. 很显然,愚蠢的我一开始并想不到什么多重背包二进制优化```因为我连听都没有听 ...
- HDOJ(HDU).2844 Coins (DP 多重背包+二进制优化)
HDOJ(HDU).2844 Coins (DP 多重背包+二进制优化) 题意分析 先把每种硬币按照二进制拆分好,然后做01背包即可.需要注意的是本题只需要求解可以凑出几种金钱的价格,而不需要输出种数 ...
- HDOJ(HDU).1059 Dividing(DP 多重背包+二进制优化)
HDOJ(HDU).1059 Dividing(DP 多重背包+二进制优化) 题意分析 给出一系列的石头的数量,然后问石头能否被平分成为价值相等的2份.首先可以确定的是如果石头的价值总和为奇数的话,那 ...
- HDOJ(HDU).2191. 悼念512汶川大地震遇难同胞――珍惜现在,感恩生活 (DP 多重背包+二进制优化)
HDOJ(HDU).2191. 悼念512汶川大地震遇难同胞――珍惜现在,感恩生活 (DP 多重背包+二进制优化) 题意分析 首先C表示测试数据的组数,然后给出经费的金额和大米的种类.接着是每袋大米的 ...
- hdu 1171 Big Event in HDU(多重背包+二进制优化)
题目链接:hdu1171 思路:将多重背包转为成完全背包和01背包问题,转化为01背包是用二进制思想,即件数amount用分解成若干个件数的集合,这里面数字可以组合成任意小于等于amount的件数 比 ...
- hdu 2191 (多重背包+二进制优化)
Problem Description 急!灾区的食物依然短缺!为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品, ...
- Coins(多重背包+二进制优化)
Problem Description Whuacmers use coins.They have coins of value A1,A2,A3...An Silverland dollar. On ...
- Cash Machine POJ - 1276 多重背包二进制优化
题意:多重背包模型 n种物品 每个m个 问背包容量下最多拿多少 这里要用二进制优化不然会超时 #include<iostream> #include<cstdio> #in ...
- BZOJ.3425.[POI2013]Polarization(DP 多重背包 二进制优化)
BZOJ 洛谷 最小可到达点对数自然是把一条路径上的边不断反向,也就是黑白染色后都由黑点指向白点.这样答案就是\(n-1\). 最大可到达点对数,容易想到找一个点\(a\),然后将其子树分为两部分\( ...
随机推荐
- python第三方库的四种安装方法
1,直接pip install安装 2,在python-->default setting-->project interprer-->add 3,在这个链接里找到需要的包,下载 h ...
- kubernetes 编排详解 资源分配
########给pod 分配cpu和内存资源apiVersion: v1 kind: Pod metadata: name: frontend spec: containers: - name: d ...
- Codeforces Round #419 Div. 1
A:暴力枚举第一列加多少次,显然这样能确定一种方案. #include<iostream> #include<cstdio> #include<cmath> #in ...
- POJ 3481 Double Queue
平衡树.. 熟悉些fhq-Treap,为啥我在poj读入优化不能用啊 #include <iostream> #include <cstdio> #include <ct ...
- jQuery 方式模拟提交表单
//add test moudle define(function(require , exports , module) { //=========== 不使用模块化只使用如下代码即可 start ...
- Gogs 部署安装(Linux)
环境 centos7:golang+mysqldb+git. 安装配置环境[mysql装了请跳过] yum install mysql-community-server go git -y 配置防火墙 ...
- [CF1131C]Birthday【贪心】
题目描述 有 n n个数摆放在一个环形中(最后一个与第一个相邻),需要改变这些数的顺序,使得相邻两个数的最大绝对差最小.如果有多种最佳方案,输出任意一种. (翻译来自洛谷) 分析 首先收尾相接,那么很 ...
- html图像、绝对路径和相对路径,链接
html图像 <img>标签可以在网页上插入一张图片,它是独立使用的标签,通过"src"属性定义图片的地址,通过"alt"属性定义图片加载失败时显示 ...
- 工作机制.py
rpc_server.py# !/usr/bin/env python3.5# -*- coding:utf-8 -*-# __author__ == 'LuoTianShuai'"&quo ...
- Haunted Graveyard ZOJ - 3391(SPFA)
从点(n,1)到点(1,m)的最短路径,可以转换地图成从(1,1)到(n,m)的最短路,因为有负权回路,所以要用spfa来判负环, 注意一下如果负环把终点包围在内的话, 如果用负环的话会输出无穷,但是 ...