ps:费用流增广的时候费用和流量打反了……调了一个多小时
每个数只能参与一次配对,那么这就是一个匹配嘛
我们先把每个数分解质因数,记质因子总个数为$cnt_i$,那如果$a_i/a_j$是质数当且仅当$cnt_i=cnt_j+1$且$a_i/a_j==0$
那么我们根据$cnt_i$的奇偶性把所有数分为两类,不难发现奇偶性相同的一类是不可能互相配对的,那么这就可以变成一个二分图了
很好,那么跑一个最大费用最大流就可以了
才怪……
费用流是先保证最大流再保证最大费用,并不能保证费用大于等于0
那么我们考虑贪心。每一次spfa的时候我们都找出一条费用最大的通路,而且每一次的最长路都不会大于之前的最长路。所以我们每一次沿着最长路,在价值总和不小于0的情况下尽可能的增加流量。如果找不到通路或者继续增广会使价值总和小于0,那么就退出
可以保证这个贪心一定正确
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<queue> 6 #include<cmath> 7 #define int long long 8 #define inf 0x3f3f3f3f3f3f3f3f 9 using namespace std; 10 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 11 char buf[1<<21],*p1=buf,*p2=buf; 12 template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;} 13 inline int read(){ 14 #define num ch-'0' 15 char ch;bool flag=0;int res; 16 while(!isdigit(ch=getc())) 17 (ch=='-')&&(flag=true); 18 for(res=num;isdigit(ch=getc());res=res*10+num); 19 (flag)&&(res=-res); 20 #undef num 21 return res; 22 } 23 const int N=205,M=500005; 24 int head[N],Next[M],ver[M],edge[M],flow[M],tot=1; 25 inline void add(int u,int v,int e,int f){ 26 ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e,flow[tot]=f; 27 ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=-e,flow[tot]=0; 28 } 29 int solve(int n){ 30 int tot=0,s=sqrt(n); 31 for(int i=2;i<=s&&i<=n;++i) 32 while(n%i==0) ++tot,n/=i;if(n>1) ++tot; 33 return tot; 34 } 35 int dis[N],S,T,vis[N],Pre[N],ans,sum,n; 36 int a[N],b[N],c[N],cnt[N]; 37 queue<int> q; 38 bool spfa(){ 39 for(int i=S;i<=T;++i) vis[i]=0,dis[i]=-inf; 40 q.push(S),vis[S]=1,dis[S]=0,Pre[T]=-1; 41 while(!q.empty()){ 42 int u=q.front();q.pop();vis[u]=0; 43 for(int i=head[u];i;i=Next[i]){ 44 int v=ver[i]; 45 if(flow[i]&&dis[v]<dis[u]+edge[i]){ 46 dis[v]=dis[u]+edge[i],Pre[v]=i; 47 if(!vis[v]) q.push(v),vis[v]=1; 48 } 49 } 50 } 51 return ~Pre[T]; 52 } 53 bool add_flow(){ 54 int fl=inf,f; 55 for(int i=Pre[T];i;i=Pre[ver[i^1]]) 56 cmin(fl,flow[i]);f=dis[T]*fl; 57 if(sum+f>=0){ 58 sum+=f,ans+=fl; 59 for(int i=Pre[T];i;i=Pre[ver[i^1]]) 60 flow[i]-=fl,flow[i^1]+=fl;return 1; 61 } 62 else return ans+=sum/(-dis[T]),0; 63 } 64 int dinic(){ 65 while(spfa()&&add_flow());return ans; 66 } 67 signed main(){ 68 //freopen("testdata.in","r",stdin); 69 n=read(); 70 for(int i=1;i<=n;++i) a[i]=read(); 71 for(int i=1;i<=n;++i) b[i]=read(); 72 for(int i=1;i<=n;++i) c[i]=read(); 73 S=0,T=n+1; 74 for(int i=1;i<=n;++i) cnt[i]=solve(a[i]); 75 for(int i=1;i<=n;++i) 76 cnt[i]&1?add(S,i,0,b[i]):add(i,T,0,b[i]); 77 for(int i=1;i<=n;++i) 78 if(cnt[i]&1) 79 for(int j=1;j<=n;++j) 80 if((cnt[i]+1==cnt[j]&&a[j]%a[i]==0)|| 81 (cnt[j]+1==cnt[i]&&a[i]%a[j]==0)) 82 add(i,j,c[i]*c[j],inf); 83 printf("%lld ",dinic()); 84 return 0; 85 }