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 */