zoukankan      html  css  js  c++  java
  • CodeForces 755F(贪心+多重背包二进制优化)

    CodeForces 755F PolandBall and Gifts

    题意:n个人相互送礼物,每个人只会另外一个人(一定不会是自己),而且每个人都会被送礼物。满足以下条件的人可以收到礼物:1.自己送别人礼物;2.有人送自己礼物。现在需要让k个人的礼物无法送出,问最少和最多能有多少人收不到礼物。

    题解:相互送礼物的人可以分成环,所以先把环找出来。对于最大值,贪心就好。最小值需要用到多重背包,但是直接的背包会因为复杂度太高而T掉,外加本题只需要求出多重背包的可行性,所以在别人那里学了一发二进制优化。

    代码略搓。。。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 using namespace std;
     6 int f[1000005];
     7 int find(int x){
     8     return f[x]==x?x:f[x]=find(f[x]);
     9 }
    10 int merge(int x,int y){
    11     int fx=find(x);
    12     int fy=find(y);
    13     f[fx]=fy;
    14 }
    15 int a[1000006];
    16 int s[1000006],tot;
    17 int num[1000006];
    18 int b[1000006],c[1000006],cnt;
    19 int d[1000006];
    20 int dp[1000006];
    21 int n,k;
    22 int main(){
    23     scanf("%d%d",&n,&k);
    24     for(int i=1;i<=n;i++) f[i]=i;
    25     for(int i=1;i<=n;i++){
    26         scanf("%d",&a[i]);
    27         merge(i,a[i]);
    28     }
    29     if(k==0){
    30         printf("0 0
    ");
    31         return 0;
    32     }
    33     for(int i=1;i<=n;i++) num[find(i)]++;
    34     for(int i=1;i<=n;i++){
    35         if(num[i]!=0){
    36             tot++;
    37             s[tot]=num[i];
    38         }
    39     }
    40     sort(s+1,s+tot+1);
    41     int mi=k,ma=0;
    42     int p=k,res=n;
    43     for(int i=1;i<=tot;i++){
    44         int kk=s[i]/2;
    45         if(p>=kk){
    46             ma+=kk*2;
    47             p-=kk;
    48             res-=kk*2;
    49         }
    50         else{
    51             ma+=p*2;
    52             p=0;
    53         }
    54         if(p==0||res==0)break;
    55     }
    56     ma+=min(p,res);
    57     memset(dp,0,sizeof(dp));
    58     for(int i=1;i<=tot;i++){
    59         if(s[i]==s[i-1]) c[cnt]++;
    60         else c[++cnt]=1,b[cnt]=s[i];
    61     }
    62     tot=0;
    63     for(int i=1;i<=cnt;i++){
    64         for(int j=1;c[i];j<<=1){
    65             int temp=min(c[i],j);
    66             d[++tot]=b[i]*temp;
    67             c[i]-=temp;
    68         }
    69     }
    70     dp[0]=true;
    71     for(int i=1;i<=tot;i++){
    72         for(int j=k-d[i];j>=0;j--)
    73             if(dp[j]>0) dp[j+d[i]]=1;
    74     }
    75     if(!dp[k]) mi++;
    76     printf("%d %d
    ",mi,ma);
    77 
    78     return 0;
    79 }
    Psong
  • 相关阅读:
    机器学习--避免过度拟合 笔记
    《机器学习》第三章 决策树学习 笔记加总结
    《机器学习》第二章 概念学习和一般到特殊序
    《机器学习》第一章 引言 笔记加总结
    jmeter+ant生成html报告
    jmeter之beanshell使用
    html常用标签
    css样式
    fiddler设置重定向
    fiddler设置断点
  • 原文地址:https://www.cnblogs.com/N-Psong/p/6307232.html
Copyright © 2011-2022 走看看