标签:com 网络 display sizeof car ini freopen euler sed
题目链接: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 }
Educational Codeforces Round 21 F. Card Game(网络流之最大点权独立集)
标签:com 网络 display sizeof car ini freopen euler sed
原文地址:http://www.cnblogs.com/bin-gege/p/6916070.html