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\n");
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\n",mi,ma);
77 
78     return 0;
79 }
Psong

 

posted on 2017-01-19 16:39  Psong  阅读(465)  评论(0编辑  收藏  举报

导航