Codeforces 755 F. PolandBall and Gifts (简单贪心+二进制优化多重背包)

27 篇文章 1 订阅
19 篇文章 2 订阅


F. PolandBall and Gifts
time limit per test
1.5 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

It's Christmas time! PolandBall and his friends will be giving themselves gifts. There are n Balls overall. Each Ball has someone for whom he should bring a present according to some permutation ppi ≠ i for all i.

Unfortunately, Balls are quite clumsy. We know earlier that exactly k of them will forget to bring their gift. A Ball number i will get his present if the following two constraints will hold:

  1. Ball number i will bring the present he should give.
  2. Ball x such that px = i will bring his present.

What is minimum and maximum possible number of kids who will not get their present if exactly k Balls will forget theirs?

Input

The first line of input contains two integers n and k (2 ≤ n ≤ 1060 ≤ k ≤ n), representing the number of Balls and the number of Balls who will forget to bring their presents.

The second line contains the permutation p of integers from 1 to n, where pi is the index of Ball who should get a gift from the i-th Ball. For all ipi ≠ i holds.

Output

You should output two values — minimum and maximum possible number of Balls who will not get their presents, in that order.

Examples
input
5 2
3 4 1 5 2
output
2 4
input
10 1
2 3 4 5 6 7 8 9 10 1
output
2 2
Note

In the first sample, if the third and the first balls will forget to bring their presents, they will be th only balls not getting a present. Thus the minimum answer is 2. However, if the first ans the second balls will forget to bring their presents, then only the fifth ball will get a present. So, the maximum answer is 4.


题意:

这是一个带礼物的置换,只有当你给带了礼物且给你带礼物的那个人带了礼物你才能获得礼物,现在有k个人没带礼物,问最少和最多有多少人无法获得礼物;

思路:
先把这个置换写成循环的形式,对于一个长度为x的循环,现在假设其中y个没带礼物,那么最少会有y+1个人无法获得礼物,如果x==y,那么就有y个人无法获得礼物,最多有2*y个人没法获得礼物;
所以现在答案的贪心条件就明晰了;
假设这个置换可以写成num个循环,分别长为bi,那么其中一些bi的和等于k那么minans=k,or minans=k+1;这时发现是一个背包问题,可以发现bi的种类大约在sqrt(n)附近,
所以像多重背包那样把bi的数目转化成二进制的和,这样复杂度就降下来了,还有多重背包可以用单调队列优化
maxans直接贪心就好;

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <bitset>
using namespace std;
const int maxn = 1e6 + 5;
int a[maxn], book[maxn], w[maxn], num[maxn], val[maxn];
bitset<maxn> dp;
int main()
{
    int n, k, tot = 0, totl = 0, maxans = 0, minans = 0;
    scanf("%d%d", &n, &k);
    for(int i = 1; i <= n; i++)
        scanf("%d", &a[i]);
    for(int i = 1; i <= n; i++)
    {
        int index = i, cnt = 0;
        while(!book[index])
        {
            book[index] = 1;
            index = a[index];
            cnt++;
        }
        if(!cnt) continue;
        if(num[cnt]) num[cnt]++;
        else w[++tot] = cnt, num[cnt] = 1;
    }
    for(int i = 1; i <= tot; i++)
        maxans += w[i] / 2 * num[w[i]];
    if(maxans >= k) maxans = k*2;
    else maxans = maxans*2 + k - maxans;
    maxans = min(maxans, n);  //这里要判断下, 是不是大于了总人数。。wa了几发。。
    for(int i = 1; i <= tot; i++)
    {
        for(int k = 1; k <= num[w[i]]; k<<=1)
        {
            val[++totl] = k*w[i];
            num[w[i]] -= k;
        }
        if(num[w[i]] > 0)
            val[++totl] = num[w[i]]*w[i];
    }
    dp.set(0);
    for(int i = 1; i <= totl; i++)
        dp |= (dp << val[i]);
    if(dp.test(k))
        printf("%d %d\n", k, maxans);
    else
        printf("%d %d\n", k+1, maxans);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值