https://www.luogu.com.cn/problem/P4068
质因数分解然后建立二分图,跑费用流
具体看第一个官方题解的代码就好了,我想说的是费用流控制流量使得费用大于0且流量最大的方法,具体看代码,受益匪浅
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
#include<queue>
#include<cstdio>
using namespace std;
typedef long long ll;
const ll inf = 1e16;
const int maxn = 1005;
const int M = 1005;
queue<int> que;
int head[maxn];
struct Edge{
int id,nex;
ll w,f;
}edge[M<<1];
int cnt = 0;
void init(){
cnt=0;
memset(head,-1,sizeof(head));
while(que.size()) que.pop();
}
void add_(int x,int y,ll f,ll w){
edge[cnt].id = y;
edge[cnt].f = f;
edge[cnt].w = w;
edge[cnt].nex = head[x];
head[x] = cnt ++ ;
}
void add(int x,int y,ll f,ll w){
add_(x,y,f,w);
add_(y,x,0,-w);
}
int n,m;
int vis[maxn];
ll dis[maxn];
ll mflow[maxn];
int per[maxn];
int spfa(int s,int t){
for (int i = 0; i<= n+16 ; i++ ){
vis[i] = 0;
dis[i] = inf;
}
mflow[s] = inf;
que.push(s);
dis[s] = 0;
vis[s] = 1;
while(que.size()){
int x= que.front();
que.pop();
vis[x] = 0;
for (int i = head[x]; ~i; i = edge[i].nex){
int v = edge[i].id;
if(dis[v] > dis[x] + edge[i].w && edge[i].f){
dis[v] = dis[x] + edge[i].w;
per[v] = i;
mflow[v] = min(mflow[x],edge[i].f);
if(vis[v]) continue;
vis[v] = 1;
que.push(v);
}
}
}
if(dis[t] != inf) return 1;
else return 0;
}
///!!!!!!!
void update(int s,int t, ll& flow){
ll minn = mflow[t];
for (int i = t; i != s; i = edge[per[i] ^ 1].id){//沿着路走
int x = per[i];
edge[x].f -= minn;
edge[x^1].f += minn;
}
flow += minn;
}
int len = 0;
ll solve(int s,int t, ll& flow){
ll ans = 0;
len = 0;
while(spfa(s,t)){//鐢╯pfa寮€璺?
if(ans + dis[t] * mflow[t] > 0){
flow -= ans/dis[t];
return ans;
}
ans += dis[t] * mflow[t];
update(s,t,flow);
}
return ans;
}
//----------------------------------------------------------------------------------------
//以上是网络流模板
const int Maxn = 1e5+7;
int prime[Maxn];
int Mark[Maxn+1];
int sieve() {
int p = 0;
Mark[0] = 1; Mark[1] = 1;
for (int i = 2; i < Maxn; i++){
if (Mark[i] == 0) {
prime[p++] = i;
}
for (int j = 0; j < p && prime[j] * i < Maxn; j++){
Mark[i * prime[j]] = 1;
if (i % prime[j] == 0) {
break;
}
}
}
return p;
}
int chal;
ll a[maxn],b[maxn],c[maxn];
int ans[maxn];
int cal(int x){
int cns = 0;
for(int i = 2;1LL*i*i<= x;i++){
while(x % i == 0){
x /= i;
cns++;
}
}
if(x > 1 ) cns ++;
return cns;
}
int main(){
init();
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
for(int i=1;i<=n;i++){
scanf("%lld",&b[i]);
}
for(int i=1;i<=n;i++){
scanf("%lld",&c[i]);
}
for(int i=1;i<=n;i++){
ans[i] = cal(a[i]);//有几个质数因子
}
for(int i=1;i<=n;i++){
if(ans[i] & 1 ){
for(int j=1;j<=n;j++){
if(ans[j] %2 == 0 ){
if(a[i] % a[j] == 0 && ans[j] + 1 == ans[i]){
add(i,j,inf,-1LL*c[i]*c[j]);
}
else if(a[j] % a[i] == 0 && ans[i] + 1== ans[j] ){
add(i,j,inf,-1LL*c[i]*c[j]);
}
}
}
}
}
int s,t;
s = 0;
t = n+11;
for(int i=1;i<=n;i++){
if(ans[i] & 1){
add(s,i,b[i],0);
// cout<<s<<" "<<i<<" "<<b[i]<<endl;
}
else{
add(i,t,b[i],0);
// cout<<i<<" "<<t<<" "<<b[i]<<endl;
}
}
ll f = 0;
ll cc = solve(s,t,f);
printf("%lld
",f);
}
/*
3
2 4 8
2 200 7
-1 -2 1
4
*/