bzoj4514: [Sdoi2016]数字配对
很沙茶很沙茶。。调了一个下午。。。结果就是下界大了。。
做法:可以得到一个num数组,表示这个数的质因数个数,然后若A[i]%A[j]==0并且num[i]==num[j]+1 说明它可以匹配
这样一来又可以发现按奇偶分是二分图没有环,二分答案,最大费用最大流,判断是否满流且费用大于0即可。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; const int inf=(1<<30); int A[11000],B[11000],num[11000]; LL C[11000]; int getnum(int k) { int s=0; for(int i=2;i*i<=k;i++) { if(k%i==0) while(k%i==0)k/=i,s++; } if(k>1)s++; return s; } //----------------------------------------- int n,st,ed,S; struct node { int x,y,c,next,other;LL d; }a[210000],e[210000];int len,last[11000],elen,elast[11000]; void eins(int x,int y,int c,LL d) { int k1,k2; elen++;k1=elen; e[elen].x=x;e[elen].y=y;e[elen].c=c;e[elen].d=d; e[elen].next=elast[x];elast[x]=elen; elen++;k2=elen; e[elen].x=y;e[elen].y=x;e[elen].c=0;e[elen].d=-d; e[elen].next=elast[y];elast[y]=elen; e[k1].other=k2; e[k2].other=k1; } void composition() { elen=0;memset(elast,0,sizeof(elast)); st=n+1;ed=n+2;S=n+3; for(int i=1;i<=n;i++) if(num[i]%2==1)eins(st,i,B[i],0); else eins(i,ed,B[i],0); for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) if((num[i]+1==num[j]&&A[j]%A[i]==0)||(num[i]==num[j]+1&&A[i]%A[j]==0)) if(num[i]%2==1)eins(i,j,inf,C[i]*C[j]); else eins(j,i,inf,C[i]*C[j]); } //~~~~~~~~~~~~~~ void ins(int x,int y,int c,LL d) { int k1,k2; len++;k1=len; a[len].x=x;a[len].y=y;a[len].c=c;a[len].d=d; a[len].next=last[x];last[x]=len; len++;k2=len; a[len].x=y;a[len].y=x;a[len].c=0;a[len].d=-d; a[len].next=last[y];last[y]=len; a[k1].other=k2; a[k2].other=k1; } //----------------------------------------- int cc;LL cost; int list[11000];bool v[11000]; LL d[11000]; int c[11000],pre[11000]; bool spfa() { for(int i=1;i<=n+4;i++)d[i]=-(LL(inf))*(LL(inf)); d[S]=0; memset(c,0,sizeof(c));c[S]=inf; memset(pre,0,sizeof(pre)); memset(v,false,sizeof(v));v[S]=true; int head=1,tail=2;list[head]=S; while(head!=tail) { int x=list[head]; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(d[y]<d[x]+a[k].d&&a[k].c>0) { d[y]=d[x]+a[k].d; c[y]=min(c[x],a[k].c); pre[y]=k; if(v[y]==false) { v[y]=true; list[tail]=y; tail++;if(tail==10100)tail=1; } } } v[x]=false; head++;if(head==10100)head=1; } if(d[ed]<=-(LL(inf))*(LL(inf)))return false; else { cc+=c[ed]; cost+=d[ed]*c[ed]; int y=ed; while(pre[y]!=0) { int k=pre[y]; a[k].c-=c[ed]; a[a[k].other].c+=c[ed]; y=a[k].x; } return true; } } bool check(int mid) { len=elen; memcpy(a,e,sizeof(a)); memcpy(last,elast,sizeof(last)); ins(S,st,mid,0); cc=0;cost=0; while(spfa()==true); if(cc==mid&&cost>=0)return true; else return false; } int main() { freopen("pair.in","r",stdin); freopen("pair.out","w",stdout); int sum=0; scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&A[i]),num[i]=getnum(A[i]); for(int i=1;i<=n;i++)scanf("%d",&B[i]),sum+=B[i]; for(int i=1;i<=n;i++)scanf("%lld",&C[i]); composition(); int l=0,r=sum/2,ans=0; while(l<=r) { int mid=(l+r)/2; if(check(mid)==true) { l=mid+1; ans=mid; } else r=mid-1; } printf("%d\n",ans); return 0; }
pain and happy in the cruel world.