首页 > 代码库 > Educational Codeforces Round 21 F. Card Game(网络流之最大点权独立集)

Educational Codeforces Round 21 F. Card Game(网络流之最大点权独立集)

题目链接:Educational Codeforces Round 21 F. Card Game

题意:

有n个卡片,每个卡片有三个值:p,c,l;

现在让你找一个最小的L,使得满足选出来的卡片l<=L,并且所有卡片的p的和不小于k。

选择卡片时有限制,任意两张卡片的c之和不能为质数。

题解:

和hdu 1565 方格取数(2)一样,都是求最大点权独立集。

不难看出来,这题再多一个二分。

注意的是在构造二部图的时候,按照c值的奇偶性构造。

当c==1时要单独处理,因为如果有多个c==1的卡片,我们肯定会选当中p值最大的卡片。

技术分享
  1 #include<bits/stdc++.h>
  2 #define F(i,a,b) for(int i=a;i<=b;i++)
  3 #define ___ freopen("in.txt","r",stdin);
  4 using namespace std;
  5 typedef long long ll;
  6 
  7 namespace Euler{
  8     const int N=2e5+7;
  9     int primes[N],tot=0;
 10     bool vis[N];
 11     void euler(){
 12         memset(vis,0,sizeof(vis));
 13         F(i,2,N){
 14             if(!vis[i])primes[++tot]=i;
 15             F(j,1,tot){
 16                 if(i*primes[j]>N)break;
 17                 vis[i*primes[j]]=1;
 18                 if(i%primes[j]==0)break;
 19             }
 20         }
 21     }
 22 }
 23 
 24 namespace ISAP{
 25     const int N=120,inf=~0U>>2,M=20000;
 26     struct edge{int t,f;edge*nxt,*pair;}*g[N],*d[N],pool[M],*cur=pool;
 27     int i,S,T,h[N],gap[N],maxflow;
 28     void init(int ss,int tt){for(S=ss,T=tt,cur=pool,i=1;i<=T;i++)g[i]=d[i]=NULL,h[i]=gap[i]=0;}
 29     void add(int s,int t,int f){
 30        // printf("s=%d,t=%d,f=%d\n",s,t,f);
 31         edge*p=cur++;p->t=t,p->f=f,p->nxt=g[s],g[s]=p;
 32         p=cur++,p->t=s,p->f=0,p->nxt=g[t],g[t]=p;
 33         g[s]->pair=g[t],g[t]->pair=g[s];
 34     }
 35     int sap(int v,int flow){
 36         if(v==T)return flow;
 37         int rec=0;
 38         for(edge*p=d[v];p;p=p->nxt)if(h[v]==h[p->t]+1&&p->f){
 39             int ret=sap(p->t,min(flow-rec,p->f));
 40             p->f-=ret;p->pair->f+=ret;d[v]=p;
 41             if((rec+=ret)==flow)return flow;
 42         }
 43         if(!(--gap[h[v]]))h[S]=T;
 44         gap[++h[v]]++;d[v]=g[v];
 45         return rec;
 46     }
 47     int get_ans(){
 48         for(gap[maxflow=0]=T,i=1;i<=T;i++)d[i]=g[i];
 49         while(h[S]<T)maxflow+=sap(S,inf);
 50         return maxflow;
 51     }
 52 }
 53 
 54 int n,k;
 55 struct node
 56 {
 57     int p,c,l;
 58     node(int a=0,int b=0,int _c=0):p(a),c(b),l(_c){}
 59 }a[200],tmp[200];
 60 
 61 bool Find(int x)
 62 {
 63     using namespace Euler;
 64     int now=lower_bound(primes+1,primes+1+tot,x)-primes;
 65     if(now<=tot&&x==primes[now])return 1;
 66     return 0;
 67 }
 68 
 69 int check(int mid)
 70 {
 71     using namespace ISAP;
 72     int ed=0,sum=0,mxp=0,mxidx=-1;
 73     F(i,1,n)if(a[i].l<=mid)
 74     {
 75         if(a[i].c==1){if(a[i].p>mxp)mxp=a[i].p,mxidx=i;}
 76         else tmp[++ed]=a[i],sum+=a[i].p;
 77     }
 78     if(mxidx!=-1)tmp[++ed]=a[mxidx],sum+=a[mxidx].p;
 79     init(ed+1,ed+2);
 80     F(i,1,ed)if(tmp[i].c&1)add(S,i,tmp[i].p);else add(i,T,tmp[i].p);
 81     F(i,1,ed)if(tmp[i].c&1)
 82     {
 83         F(j,1,ed)if(tmp[j].c%2==0&&Find(tmp[i].c+tmp[j].c))add(i,j,inf);
 84     }
 85     return sum-get_ans()>=k;
 86 }
 87 
 88 int main()
 89 {
 90     Euler::euler();
 91     scanf("%d%d",&n,&k);
 92     F(i,1,n)scanf("%d%d%d",&a[i].p,&a[i].c,&a[i].l);
 93     int l=1,r=n,mid,ans=-1;
 94     while(l<=r)
 95     {
 96         mid=l+r>>1;
 97         if(check(mid))r=mid-1,ans=mid;
 98         else l=mid+1;
 99     }
100     printf("%d\n",ans);
101     return 0;
102 }
View Code

 

Educational Codeforces Round 21 F. Card Game(网络流之最大点权独立集)