4514: [Sdoi2016]数字配对
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 820 Solved: 345
[Submit][Status][Discuss]
Description
有 n 种数字,第 i 种数字是 ai、有 bi 个,权值是 ci。
若两个数字 ai、aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数,
那么这两个数字可以配对,并获得 ci×cj 的价值。
一个数字只能参与一次配对,可以不参与配对。
在获得的价值总和不小于 0 的前提下,求最多进行多少次配对。
Input
第一行一个整数 n。
第二行 n 个整数 a1、a2、……、an。
第三行 n 个整数 b1、b2、……、bn。
第四行 n 个整数 c1、c2、……、cn。
Output
一行一个数,最多进行多少次配对
Sample Input
3
2 4 8
2 200 7
-1 -2 1
2 4 8
2 200 7
-1 -2 1
Sample Output
4
HINT
n≤200,ai≤10^9,bi≤10^5,∣ci∣≤10^5
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 #include <cmath> 6 using namespace std; 7 const int maxn=210; 8 const int maxm=40010; 9 long long INF=1000000000000000LL; 10 int cnt=1,fir[maxn],nxt[maxm],to[maxm],ID[maxn],path[maxn],n; 11 long long a[maxn],b[maxn],c[maxn],cost[maxm],cap[maxm],dis[maxn],val[maxm]; 12 13 void addedge(int a,int b,long long c,long long v){ 14 nxt[++cnt]=fir[a];to[cnt]=b;cap[cnt]=c;val[cnt]=v;fir[a]=cnt; 15 } 16 17 int S,T; 18 long long Spfa(){ 19 queue<int>q; 20 q.push(S); 21 for(int i=S;i<=T;i++) 22 dis[i]=-INF;dis[S]=0; 23 while(!q.empty()){ 24 int node=q.front();q.pop(); 25 for(int i=fir[node];i;i=nxt[i]) 26 if(cap[i]&&dis[node]+val[i]>dis[to[i]]){ 27 dis[to[i]]=val[i]+dis[node]; 28 path[to[i]]=i; 29 q.push(to[i]); 30 } 31 } 32 33 return dis[T]==-INF?INF:dis[T]; 34 } 35 36 long long Aug(){ 37 int p=T; 38 long long f=INF; 39 while(p!=S){ 40 f=min(f,cap[path[p]]); 41 p=to[path[p]^1]; 42 } 43 p=T; 44 while(p!=S){ 45 cap[path[p]]-=f; 46 cap[path[p]^1]+=f; 47 p=to[path[p]^1]; 48 } 49 return f; 50 } 51 52 long long MCMF(){ 53 long long ret=0,now=0,c,d; 54 while((d=Spfa())!=INF){ 55 c=Aug(); 56 if(c*d+now<0) 57 return ret-now/d; 58 else{ret+=c;now+=c*d;} 59 } 60 return ret; 61 } 62 63 64 bool Get_ID(int x){ 65 bool ret=true; 66 for(int i=2,m=(int)sqrt(x);i<=m;i++) 67 if(x%i==0){while(x%i==0)x/=i,ret=!ret;} 68 if(x!=1)ret=!ret; 69 return ret; 70 } 71 72 bool IS_Prime(int x){ 73 for(int i=2,m=(int)sqrt(x);i<=m;i++) 74 if(x%i==0)return false; 75 return true; 76 } 77 78 int main(){ 79 scanf("%d",&n);S=0;T=n+1; 80 for(int i=1;i<=n;i++)scanf("%lld",&a[i]); 81 for(int i=1;i<=n;i++)scanf("%lld",&b[i]); 82 for(int i=1;i<=n;i++)scanf("%lld",&c[i]); 83 for(int i=1;i<=n;i++)ID[i]=Get_ID(a[i]); 84 for(int i=1;i<=n;i++){ 85 if(!ID[i]){ 86 addedge(S,i,b[i],0);addedge(i,S,0,0); 87 for(int j=1;j<=n;j++) 88 if(ID[j]){ 89 long long x=a[i],y=a[j];if(x<y)swap(x,y); 90 if(x%y==0&&IS_Prime(x/y)){ 91 addedge(i,j,INF,c[i]*c[j]); 92 addedge(j,i,0,-c[i]*c[j]); 93 } 94 } 95 } 96 else{addedge(i,T,b[i],0);addedge(T,i,0,0);} 97 } 98 printf("%lld ",MCMF()); 99 return 0; 100 }