p4068 [SDOI2016]数字配对

传送门

分析

我们考虑对所有a[i]质因数分解,然后记cnt[i]为a[i]是由几个质数相乘得到的

然后我们建一个二分图,左面为所有cnt[i]为奇数的点,右面是为偶数的点

我们从源点向左面点连容量b[i]花费0的边,从右面点向汇点连容量b[i]花费0的边

然后两排点之间符合条件的点对连容量inf花费c[i]*c[j]的边

然后跑总花费不小于0的最大费用最大流即可

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
#define int long long
const int inf = 1e15+7;
int n,a[500],b[500],C[500],cnt[500];
int x[500],y[500],l1,l2,s,t,Ans,now,sum;
int head[300100],w[300100],c[300100],nxt[300100],to[300100];
int fm[300100],ano[300100],S;
inline void add(int x,int y,int z,int cost){
    nxt[++S]=head[x];head[x]=S;to[S]=y;w[S]=z;c[S]=cost;fm[S]=x;
    nxt[++S]=head[y];head[y]=S;to[S]=x;w[S]=0;c[S]=-cost;fm[S]=y;
    ano[S]=S-1;ano[S-1]=S;
}
inline int work(int x){
    int i,j,k=0;
    for(i=2;i<=sqrt(x);i++)
      while(x%i==0)x/=i,k++;
    if(x>1)k++;
    return k;
}
queue<int>q;
int iq[100100],nf[100100],la[100100],d[100100];
inline void go(){
    int i,j,k;
    la[s]=0;
    while(1){
      for(i=1;i<=t;i++)d[i]=-inf;
      q.push(s);
      d[s]=0,nf[s]=inf,iq[s]=1;
      while(!q.empty()){
          int u=q.front();
          q.pop(),iq[u]=0;
          for(i=head[u];i;i=nxt[i])
            if(w[i]&&d[to[i]]<d[u]+c[i]){
              d[to[i]]=d[u]+c[i];
              la[to[i]]=i;
              nf[to[i]]=min(w[i],nf[u]);
              if(!iq[to[i]]){
                q.push(to[i]);
                iq[to[i]]=1;
              }
            }
      }
      int be=now,ans=Ans,i=la[t];
      if(!nf[t]||d[t]==-inf)return;
      while(i){
          w[i]-=nf[t];
          w[ano[i]]+=nf[t];
          now+=nf[t]*c[i];
          i=la[fm[i]];
      }
      Ans+=nf[t];
      if(now<0){
          Ans=ans+be/abs(d[t]);
          return;
      }
    }
}
signed main(){
    int i,j,k;
    scanf("%lld",&n);
    s=n+1,t=n+2;
    for(i=1;i<=n;i++)scanf("%lld",&a[i]),cnt[i]=work(a[i]);
    for(i=1;i<=n;i++)scanf("%lld",&b[i]);
    for(i=1;i<=n;i++)scanf("%lld",&C[i]);
    for(i=1;i<=n;i++)if(cnt[i]&1)
      for(j=1;j<=n;j++)
        if((cnt[i]==cnt[j]+1&&a[i]%a[j]==0)
          ||(cnt[j]==cnt[i]+1&&a[j]%a[i]==0))add(i,j,inf,C[i]*C[j]);
    for(i=1;i<=n;i++)
      if(cnt[i]&1)add(s,i,b[i],0);
        else add(i,t,b[i],0);
    go();
    printf("%lld\n",Ans);
    return 0;
}

原文地址:https://www.cnblogs.com/yzxverygood/p/10354441.html

时间: 2024-10-05 12:13:17

p4068 [SDOI2016]数字配对的相关文章

Luogu P4068 [SDOI2016]数字配对(费用流)

Luogu P4068 [SDOI2016]数字配对(费用流) 根据质因子个数奇偶性划分肯定会形成一张二分图. 把所有的\(a\)分解质因数,记录其质因子个数. \(a_i \% a_j == 0\)且\(a_i\)的质因子比\(a_j\)质因子个数多1的时候,我们连边. 解决这个题目的关键是求出费用\(>0\)的时候的最大的流量. 我们要跑最大费用最大流,(具体实现是把边权取反) 这样在每一次的增广过程中,我们都可以保证费用最大且满足流最多. 但是写法有异议,待填坑. 原文地址:https:/

Luogu P4068 [SDOI2016]数字配对

反正现在做题那么少就争取做一题写一题博客吧 看到题目发现数字种类不多,而且结合价值的要求可以容易地想到使用费用流 但是我们如果朴素地建图就会遇到一个问题,若\(i,j\)符合要求,那么给\(i,j\)连的应该是双向边,但双向边怎么跑网络流? 所以我们就要考虑怎么给边定向,我们稍加观察就会发现如果\(i,j\)合法,\(j,k\)也合法,那么\(i,k\)显然是不合法的(分四类情况讨论一下都是不合法的) 考虑那个整除出一个质数的条件,我们发现如果我们定义\(ct_i\)为\(a_i\)的所有质因数

【bzoj4514】: [Sdoi2016]数字配对 图论-费用流

[bzoj4514]: [Sdoi2016]数字配对 好像正常的做法是建二分图? 我的是拆点然后 S->i cap=b[i] cost=0 i'->T cap=b[i] cost=0 然后能匹配的两点i,j 连 i->j' cap=inf cost=c[i]*c[j] 跑最大费用流,直到 cost<0 或 全部增广完 最后flow/2就是答案 1 /* http://www.cnblogs.com/karl07/ */ 2 #include <cstdlib> 3 #i

图论(费用流):BZOJ 4514 [Sdoi2016]数字配对

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 的价值. 一个数字只能参与一次配对,可以不参与配对. 在

【BZOJ4514】[Sdoi2016]数字配对 费用流

[BZOJ4514][Sdoi2016]数字配对 Description 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×cj 的价值. 一个数字只能参与一次配对,可以不参与配对. 在获得的价值总和不小于 0 的前提下,求最多进行多少次配对. Input 第一行一个整数 n. 第二行 n 个整数 a1.a2.…….an. 第三行 n 个整数 b1.b2.

4514: [Sdoi2016]数字配对

4514: [Sdoi2016]数字配对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1305  Solved: 498[Submit][Status][Discuss] Description 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×cj 的价值. 一个数字只能参与一次配对,可以不参与配对.

BZOJ 4514: [Sdoi2016]数字配对

4514: [Sdoi2016]数字配对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1606  Solved: 608[Submit][Status][Discuss] Description 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×cj 的价值. 一个数字只能参与一次配对,可以不参与配对.

[Bzoj4514][Sdoi2016]数字配对(费用流)

4514: [Sdoi2016]数字配对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2204  Solved: 865[Submit][Status][Discuss] Description 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×cj 的价值. 一个数字只能参与一次配对,可以不参与配对.

[Sdoi2016]数字配对

Time Limit: 10 SecMemory Limit: 128 MBSubmit: 1411  Solved: 535[Submit][Status][Discuss] Description 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×cj 的价值. 一个数字只能参与一次配对,可以不参与配对. 在获得的价值总和不小于 0 的前提下,求最多进