[bzoj4514]数字配对
不难证明这是个二分图,就是个费用流了。
- 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=410,M=500010;
int a[N],b[N];
ll c[N];
int mp[N][N];
int col[N];
int n;
inline bool prime(int x) {
if(x==1)return false;
for(int i=2; 1ll*i*i<=x; ++i) {
if(x%i==0)return false;
}
return true;
}
bool vis[N];
inline void dfs(int x,int co) {
if(vis[x])return;
vis[x]=true;
col[x]=co;
for(int i=1; i<=n; i++)if(mp[x][i]) {
dfs(i,co^1);
}
}
namespace graph {
const ll INF=2000000000000000000;
int S=N-2,T=N-1;
int hed[N],to[M],nxt[M];
ll val[M];
ll cap[M];
int cnt=1;
inline void adde(int u,int v,ll _c,ll _v) {
++cnt;
to[cnt]=v,nxt[cnt]=hed[u],cap[cnt]=_c,val[cnt]=_v;
hed[u]=cnt;
++cnt;
to[cnt]=u,nxt[cnt]=hed[v],cap[cnt]=0,val[cnt]=-_v;
hed[v]=cnt;
}
ll dist[N];
bool vist[N];
int pre[N];
ll incf[N];
queue<int>Q;
inline bool spfa() {
for(int i=1; i<=T; i++)vist[i]=false,dist[i]=-INF,pre[i]=-1;
Q.push(S);
dist[S]=0,incf[S]=0x3f3f3f3f;
while(!Q.empty()) {
int u=Q.front();
Q.pop();
vist[u]=false;
for(int i=hed[u]; i; i=nxt[i]) {
int v=to[i];
if(!cap[i]) {
continue;
}
if(dist[u]+val[i]>dist[v]) {
dist[v]=dist[u]+val[i];
incf[v]=min(incf[u],cap[i]);
pre[v]=i;
if(!vist[v])vist[v]=true,Q.push(v);
}
}
}
return ~pre[T];
}
ll maxflow=0,maxcost=0;
inline bool update() {
int x=T;
ll flow=incf[T],cst=dist[T];
if(cst*flow+maxcost<0) {
while(cst*flow+maxcost<0)flow--;
}
if(flow) {
while(x!=S) {
int i=pre[x];
cap[i]-=flow;
cap[i^1]+=flow;
x=to[i^1];
}
maxcost+=flow*cst;
maxflow+=flow;
}
return flow<incf[T];
}
inline void solve() {
while(spfa()) {
if(update())break;
}
printf("%lld\n",maxflow);
}
}
using namespace graph;
int main() {
scanf("%d",&n);
S=n+1,T=n+2;
for(int i=1; i<=n; i++) {
scanf("%d",&a[i]);
}
for(int i=1; i<=n; i++) {
scanf("%d",&b[i]);
}
for(int i=1; i<=n; i++) {
scanf("%lld",&c[i]);
}
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++)if(i^j) {
if(a[i]>a[j]&&a[i]%a[j]==0&&prime(a[i]/a[j])==true) {
mp[i][j]=mp[j][i]=1;
}
}
}
for(int i=1; i<=n; i++)if(!vis[i])dfs(i,0);
for(int i=1; i<=n; i++)if(!col[i]) {
adde(S,i,b[i],0);
} else {
adde(i,T,b[i],0);
}
for(int i=1; i<=n; i++)if(!col[i]) {
for(int j=1; j<=n; j++)if(mp[i][j]) {
adde(i,j,INF,1ll*c[i]*c[j]);
}
}
solve();
}