好像正常的做法是建二分图?
我的是拆点然后
S->i cap=b[i] cost=0
i‘->T cap=b[i] cost=0
然后能匹配的两点i,j 连 i->j‘ cap=inf cost=c[i]*c[j]
跑最大费用流,直到 cost<0 或 全部增广完
最后flow/2就是答案
1 /* http://www.cnblogs.com/karl07/ */ 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <cmath> 6 #include <algorithm> 7 #include <queue> 8 using namespace std; 9 10 #define ll long long 11 const ll inf=1e18; 12 const int N=1e5+5; 13 struct edge{ 14 int from,next,to; 15 ll v,c; 16 }e[N]; 17 int first[N],pr[N],prime[N],inq[N],lst[N]; 18 ll A[N],B[N],C[N],dis[N],minf[N]; 19 int S=1,T=2,ade=1,P,n; 20 queue <int> Q; 21 22 void addedge(int x,int y,ll v,ll c){ 23 e[++ade].to=y; 24 e[ade].from=x; 25 e[ade].next=first[x]; 26 e[ade].v=v; 27 e[ade].c=c; 28 first[x]=ade; 29 } 30 31 void ADE(int x,int y,ll v,ll c){ 32 addedge(x,y,v,c); 33 addedge(y,x,-v,0); 34 } 35 36 void Prime(){ 37 for (int i=2;i<40000;i++) prime[i]=1; 38 for (int i=2;i<40000;i++){ 39 if (prime[i]){ 40 pr[++pr[0]]=i; 41 for (int j=i+i;j<40000;j+=i) prime[j]=0; 42 } 43 } 44 } 45 46 bool check(ll x){ 47 if (x==1) return 0; 48 for (int i=1;i<=pr[0] && pr[i]<x ;i++) if (!(x%pr[i])) return 0; 49 return 1; 50 } 51 52 #define s e[x].to 53 #define v e[x].v 54 #define cap e[x].c 55 #define Cap e[x^1].c 56 bool SPFA(ll &mf,ll &mc){ 57 for (int i=1;i<=n*2+2;i++) dis[i]=-inf,minf[i]=inf; 58 Q.push(S),inq[S]=1,dis[S]=0; 59 while (!Q.empty()){ 60 int p=Q.front(); 61 Q.pop(),inq[p]=0; 62 for (int x=first[p];x;x=e[x].next){ 63 if (dis[s]<dis[p]+v && cap>0){ 64 dis[s]=dis[p]+v; 65 lst[s]=x; 66 minf[s]=min(minf[p],cap); 67 if (!inq[s]) Q.push(s),inq[s]=1; 68 } 69 } 70 } 71 if (dis[T]==-inf) return 0; 72 for (int x=lst[T];x;x=lst[e[x].from]) {cap-=minf[T],Cap+=minf[T];} 73 mf+=minf[T]; 74 mc+=dis[T]*minf[T]; 75 if (mc<0){ 76 mf-=mc/dis[T]+(mc%dis[T]!=0); 77 return 0; 78 } 79 return 1; 80 } 81 82 void mcmf(){ 83 ll mf=0,mc=0; 84 while (SPFA(mf,mc)); 85 printf("%lld\n",mf/2); 86 } 87 #undef s 88 #undef v 89 #undef c 90 #undef C 91 92 93 int main(){ 94 Prime(); 95 scanf("%d",&n); 96 for (int i=1;i<=n;i++) scanf("%lld",&A[i]); 97 for (int i=1;i<=n;i++) scanf("%lld",&B[i]); 98 for (int i=1;i<=n;i++) scanf("%lld",&C[i]); 99 for (int i=1;i<=n;i++){ 100 ADE(S,i+2,0,B[i]); 101 ADE(i+n+2,T,0,B[i]); 102 for (int j=1;j<=n;j++){ 103 if (A[i]>A[j] && A[i]%A[j]==0){ 104 if (check(A[i]/A[j])){ 105 ADE(i+2,j+n+2,C[i]*C[j],inf); 106 ADE(j+2,i+n+2,C[i]*C[j],inf); 107 } 108 } 109 } 110 } 111 mcmf(); 112 return 0; 113 }
时间: 2024-10-06 17:02:19