把每个点拆成两个分别在左右两边,只要两两之间能发生关系就在左右之间连边,容量为无穷,费用为代价,源连左边每个点容量为数量,费用0,右边每个点连汇容量为数量,费用为零,跑费用流,流到费用为非负的极限,最小费用最大流贪心流是正确的,非负费用最大流贪心流也一定是正确的
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<iomanip> #include<cstring> #include<cmath> #include<ctime> #include<vector> #include<stack> #include<queue> #include<set> #include<bitset> #include<map> using namespace std; #define MAXN 4010 #define MAXM 500010 #define INF 1000000000000000ll #define MOD 1000000007 #define ll long long #define eps 1e-8 struct vec{ ll to; ll fro; ll f; ll v; }; ll n; ll a[MAXN],b[MAXN],c[MAXN]; vec mp[MAXM]; ll tai[MAXN],cnt=1; ll q[MAXN],hd,tl; ll dis[MAXN]; bool iq[MAXN]; ll rd[MAXN]; ll s,t; ll answ; ll ansf; inline void be(ll x,ll y,ll z,ll zz){ mp[++cnt].to=y; mp[cnt].fro=tai[x]; tai[x]=cnt; mp[cnt].f=z; mp[cnt].v=zz; } inline void bse(ll x,ll y,ll z,ll zz){ be(x,y,z,zz); be(y,x,0,-zz); } bool spfa(){ ll i,x,y; for(i=0;i<=t;i++){ dis[i]=-INF; } hd=tl=0; dis[s]=0; iq[q[tl++]=s]=1; while(hd!=tl){ iq[x=q[hd++]]=0; hd%=MAXN; for(i=tai[x];i;i=mp[i].fro){ y=mp[i].to; if(mp[i].f&&dis[y]<dis[x]+mp[i].v){ dis[y]=dis[x]+mp[i].v; rd[y]=i; if(!iq[y]){ iq[q[tl++]=y]=1; tl%=MAXN; } } } } if(answ+dis[t]<0){ return 0; } ll flow=INF; if(dis[t]<0){ flow=answ/(-dis[t]); } for(i=t;i!=s;i=mp[rd[i]^1].to){ //<<i<<'!'; flow=min(flow,(ll)mp[rd[i]].f); } //<<endl; for(i=t;i!=s;i=mp[rd[i]^1].to){ mp[rd[i]].f-=flow; mp[rd[i]^1].f+=flow; } ansf+=flow; answ+=flow*dis[t]; //<<dis[t]<<'@'<<flow<<endl; return 1; } ll p[MAXM],tot; bool np[MAXM]; bool jud(int x){ int i; if(x==1||x==0){ return 0; } int y=sqrt(x); for(i=2;i<=y;i++){ if(!(x%i)){ return 0; } } return 1; } int main(){ ll i,j; scanf("%lld",&n); s=(n<<1|1)+1,t=s+1; for(i=1;i<=n;i++){ scanf("%lld",&a[i]); } for(i=1;i<=n;i++){ scanf("%lld",&b[i]); bse(s,i<<1,b[i],0); bse(i<<1|1,t,b[i],0); } for(i=1;i<=n;i++){ scanf("%lld",&c[i]); } for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ if(a[j]&&!(a[i]%a[j])&&jud(a[i]/a[j])){ bse(i<<1,j<<1|1,INF,c[i]*c[j]); } if(a[i]&&!(a[j]%a[i])&&jud(a[j]/a[i])){ bse(i<<1,j<<1|1,INF,c[i]*c[j]); } } } //* while(spfa()){ } //*/ printf("%lld\n",ansf/2); return 0; } /* 3 2 4 8 3 200 7 5 1 -7 */