一道费用流好题,因为跑费用流的时候每次选择的都是最大的流,所以在ans刚刚要小于零的时候统计出答案即可
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<iostream>
#include<iomanip>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<map>
using namespace std;
#define int long long
int dis[10000];
struct flow
{
int l,r,f,v;
}a[1000000];
int fir[1000000];
int nex[1000000];
int pd[10000];
int fro[10000];
int s=0,t=9999;
int v[1000000];
int num[1000000];
bool spfa()
{
static int dui[1000000];
memset(dis,0x9f,sizeof(dis));
memset(pd,0,sizeof(pd));
int top=1,my_final=2;
dui[1]=s;
dis[s]=0;
pd[s]=true;
while(top<my_final)
{
int u=dui[top++];
for(int o=fir[u];o;o=nex[o])
{
if(a[o].f!=0 && dis[u]+a[o].v>dis[a[o].r])
{
if(!pd[a[o].r])
{
pd[a[o].r]=true;
dui[my_final++]=a[o].r;
}
dis[a[o].r]=dis[u]+a[o].v;
fro[a[o].r]=o;
}
}
pd[u]=false;
}
if(dis[t]!=0x9f9f9f9f9f9f9f9fll) return true;
else return false;
}
map<int,bool> mapp;
int prime[10000];
bool vis[100000];
void init()
{
for (int i=2;i<=32000;i++)
{
if (!vis[i]) prime[++prime[0]]=i,mapp[i]=true;
for (int j=1;j<=prime[0];j++)
{
if (i*prime[j]>32000) break;
vis[i*prime[j]]=1;
if (i%prime[j]==0) break;
}
}
}
bool pj(int x)
{
int t=1;
int sum=0;
while(x!=1 && t<=prime[0])
{
while(x%prime[t]==0) x=x/prime[t],sum++;
t++;
}
if(x!=1) sum++;
return sum%2;
}
bool lei[10000];
int ans;
int flow;
int midans;
int add_flow()
{
int mid=t;
int temp=2147483647;
int cost=0;
while(mid!=s)
{
temp=min(temp,a[fro[mid]].f);
//cout<<a[fro[mid]].f<<" ";
cost+=a[fro[mid]].v;
mid=a[fro[mid]^1].r;
}
if(ans+cost*temp<0)
{
midans=flow-ans/cost;
return -1;
}
ans+=cost*temp;
mid=t;
while(mid!=s)
{
a[fro[mid]].f-=temp;
a[fro[mid]^1].f+=temp;
mid=a[fro[mid]^1].r;
}
return temp;
}
int tot=1;
void add_edge(int l,int r,int f,int v)
{
a[++tot].l=l;
a[tot].r=r;
a[tot].f=f;
a[tot].v=v;
nex[tot]=fir[l];
fir[l]=tot;
}
main()
{
int n;
scanf("%lld",&n);
init();
for(int i=1;i<=n;i++)
{
scanf("%lld",&num[i]);
lei[i]=pj(num[i]);
}
for(int i=1;i<=n;i++)
{
int x;
scanf("%lld",&x);
if(lei[i]==0)
{
add_edge(s,i,x,0);
add_edge(i,s,0,0);
}
else
{
add_edge(i,t,x,0);
add_edge(t,i,0,0);
}
}
for(int i=1;i<=n;i++) scanf("%lld",&v[i]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(i==j) continue;
if(lei[i]==0 && lei[j]==1)
{
int x=num[i],y=num[j];
if(x<y) swap(x,y);
if(x%y!=0) continue;
if(!mapp[x/y]) continue;
add_edge(i,j,100000000,v[i]*v[j]);
add_edge(j,i,0,-v[i]*v[j]);
}
}
while(spfa())
{
int t=add_flow();
if(t==-1)
{
cout<<midans;
return 0;
}
flow+=t;
}
cout<<flow;
return 0;
}