AC日记——Card Game codeforces 808f

F - Card Game

 

思路:

  题意:

    有n张卡片,每张卡片三个值,pi,ci,li;

    要求选出几张卡片使得pi之和大于等于给定值;

    同时,任意两两ci之和不得为素数;

    求选出的li的最小值,如果不能到达给定值则输出-1;

    二分+网络流最小割;

 

代码:

#include <bits/stdc++.h>

namespace data
{
    #define maxn 105
    #define maxque 200005
    
    int val[maxn],mag[maxn],lev[maxn],num,lit;
    
    #undef maxn
    #undef maxque
}

namespace init
{
    inline void in(int &justval)
    {
        int if_z=1; justval=0;
        char Cget=getchar();
        while(Cget>'9'||Cget<'0')
        {
            if(Cget=='-') if_z=-1;
            Cget=getchar();
        }
        while(Cget>='0'&&Cget<='9')
        {
            justval=justval*10+Cget-'0';
            Cget=getchar();
        }
        justval*=if_z;
    }
}

namespace solve
{
    #define maxn 105
    #define maxque 200005
    #define INF 0x7fffffff
    
    struct EdgeType
    {
        int v,f;
        
        EdgeType *next,*another;
        
    };
    struct EdgeType *head[maxn],e[maxque];
    
    int que[maxque],sum,prime[maxque*10],num,cnt,s,t,deep[maxn];
    
    bool p_[maxque*10-1];
    
    inline void edge_add(int u,int v,int f)
    {
        e[++cnt].v=v,e[cnt].f=f,e[cnt].next=head[u],head[u]=&e[cnt];
        e[++cnt].v=u,e[cnt].f=0,e[cnt].next=head[v],head[v]=&e[cnt];
        e[cnt].another=&e[cnt-1],e[cnt-1].another=&e[cnt];
    }
    
    int min(const int &tops_,const int &tops__)
    {
        if(tops_<tops__) return tops_;
        else return tops__;
    }
    
    inline bool bfs()
    {
        t=data::num+1,s=0;int h=0,tail=1;que[h]=s;
        for(int i=s;i<=t;i++) deep[i]=-1;deep[s]=0;
        while(h<tail)
        {
            int now=que[h++];
            for(EdgeType *i=head[now];i!=NULL;i=i->next)
            {
                if(deep[i->v]<0&&i->f)
                {
                    deep[i->v]=deep[now]+1;
                    if(i->v==t) return true;
                    que[tail++]=i->v;
                }
            }
        }
        return false;
    }
    
    int flowing(int now,int flow)
    {
        if(now==t||flow<=0) return flow;
        int oldflow=0;
        for(EdgeType *i=head[now];i!=NULL;i=i->next)
        {
            if(deep[i->v]==deep[now]+1&&i->f)
            {
                int pos=flowing(i->v,min(i->f,flow));
                flow-=pos,oldflow+=pos,i->f-=pos,i->another->f+=pos;
                if(!flow) return oldflow;
            }
        }
        if(!oldflow) deep[now]=-1;
        return oldflow;
    }
    
    bool dinic(int res,int lit)
    {
        while(bfs()) res-=flowing(s,INF);
        return res>=lit;
    }
    
    void ouler(int limit)
    {
        for(int i=2;i<=limit;i++)
        {
            if(!p_[i]) prime[++num]=i;
            for(int j=1;prime[j]*i<=limit&&j<=num;j++)
            {
                p_[i*prime[j]]=true;
                if(i%prime[j]==0) break;
            }
        }
    }
    
    bool check(int x)
    {
        int n=data::num,k=data::lit,res=0;s=0,t=n+1,cnt=1;
        for(int i=s;i<=t;i++) head[i]=NULL;
        int idx__=-1;
        for(int i=1;i<=n;i++)
        {
            if(data::lev[i]>x) continue;
            if(data::mag[i]==1&&data::val[i]>data::val[idx__]) idx__=i;
        }
        for(int i=1;i<=n;i++)
        {
            if(data::lev[i]>x||(data::mag[i]==1&&idx__!=i)) continue;
            res+=data::val[i];
            if(data::mag[i]&1)
            {
                edge_add(s,i,data::val[i]);
                for(int j=1;j<=n;j++)
                {
                    if(data::lev[j]>x||i==j) continue;
                    if(!(data::mag[j]&1))
                    {
                        if(!p_[data::mag[i]+data::mag[j]]) edge_add(i,j,INF);
                    }
                    else if(data::mag[i]+data::mag[j]==2) edge_add(i,j,INF);
                }
            }
            else edge_add(i,t,data::val[i]);
        }
        return dinic(res,k);
    }
    
    void binary()
    {
        ouler(maxque*10-1);
        int l=1,r=data::num,ans=-1;
        while(l<=r)
        {
            int mid=l+r>>1;
            if(check(mid)) ans=mid,r=mid-1;
            else l=mid+1;
        }
        printf("%d\n",ans);
    }
    
    #undef INF
    #undef maxn
    #undef maxque
}

int main()
{
    init::in(data::num),init::in(data::lit);
    for(int i=1;i<=data::num;i++)
    {
        init::in(data::val[i]);
        init::in(data::mag[i]);
        init::in(data::lev[i]);
    }
    solve::binary();
    return 0;
}

 

posted @ 2017-05-19 10:49  IIIIIIIIIU  阅读(299)  评论(0编辑  收藏  举报