当前位置: 首页 > news >正文

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

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 2197  Solved: 859
[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

Sample Output

4

HINT

 

 n≤200,ai≤10^9,bi≤10^5,∣ci∣≤10^5

 

Source

鸣谢Menci上传

 
啊啊啊啊啊费用流连边的时候把流量和费用搞混了调了两个小时QWQ
考场上主要遇到了两个问题:
1.如何保证费用大于0的时候流量最大
2.如何保证每个点不被重复使用
对于第一个问题,我们可以贪心解决
即在增广的过程中,如果发现当前路径继续增光不满足条件,那么增广到上限后的最大流量就是答案
对于第二个问题,我们可以把每个数质因数分解后,按照指数的奇偶分为左边和右边,这样连边的话就不会有重复了
 
#include<bits/stdc++.h>
#define int long long 
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<23,stdin),p1==p2)?EOF:*p1++)
using namespace std;
const int MAXN=1e5+10;
const int INF=1e16+10;
char buf[1<<23],*p1=buf,*p2=buf;
inline int read()
{
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
int N,S=0,T=23333;
int A[MAXN],B[MAXN],C[MAXN],cnt[MAXN];
struct node
{
    int u,v,w,f,nxt;
}edge[MAXN];
int head[MAXN],num=0;

inline void add_edge(int x,int y,int z,int f)
{
    edge[num].u=x;
    edge[num].v=y;
    edge[num].w=z;
    edge[num].f=f;
    edge[num].nxt=head[x];
    head[x]=num++;
}
void AddEdge(int x,int y,int z,int f) 
{
    add_edge(x,y,z,f);
    add_edge(y,x,-z,0);
}
inline int PrimeCut(int x)
{
    int tot=0;
    for(int i=2;i<=sqrt(x);i++)
        while(x%i==0) x/=i,tot++;
    return x>1?tot+1:tot;
}
namespace Liu
{
    int dis[MAXN],vis[MAXN],Pre[MAXN],ansflow=0,anscost=0;
    bool SPFA()
    {
        queue<int>q;
        q.push(S);
        memset(dis,0x3f,sizeof(dis));
        memset(vis,0,sizeof(vis));
        memset(Pre,0,sizeof(Pre));
        dis[S]=0;
        while(q.size()!=0)
        {
            int p=q.front();q.pop();
            vis[p]=0;
            for(int i=head[p];i!=-1;i=edge[i].nxt)
            {
                if(edge[i].f>0&&dis[edge[i].v]>dis[p]+edge[i].w)
                {
                    dis[edge[i].v]=dis[p]+edge[i].w;
                    Pre[edge[i].v]=i;
                    if(!vis[edge[i].v])
                        q.push(edge[i].v),
                        vis[edge[i].v]=1;
                }
            }
        }
        return dis[T]<INF;
    }
    bool f()
    {
        int nowflow=INF;
        for(int i=T;i!=S;i=edge[Pre[i]].u)
            nowflow=min(nowflow,edge[Pre[i]].f);
        if(anscost+nowflow*(-dis[T]) < 0) 
        {
            ansflow+=anscost/dis[T];
            return 0;
        }
        for(int i=T;i!=S;i=edge[Pre[i]].u)
            edge[Pre[i]].f-=nowflow,
            edge[Pre[i]^1].f+=nowflow;
        anscost+=nowflow*(-dis[T]);
        ansflow+=nowflow;
    //    printf("%d\n",ansflow);
        return 1; 
    }
    void MCMF()
    {
        bool flag=0;
        while(SPFA())
        {
            if( !f() )
            {
                flag=1;
                printf("%d",ansflow);
                break;
            }
        }
        if(flag==0) printf("%d",ansflow);
    }
}
void Work()
{
    for(int i=1;i<=N;i++) cnt[i]=PrimeCut(A[i]);
    for(int i=1;i<=N;i++)
        cnt[i]&1?AddEdge(S,i,0,B[i]):
                AddEdge(i+N,T,0,B[i]);
    for(int i=1;i<=N;i++)
    {
        if(cnt[i]&1)
        {
            for(int j=1;j<=N;j++)
                if( (cnt[i]+1==cnt[j]&&A[j]%A[i]==0) || (cnt[j]+1==cnt[i]&&A[i]%A[j]==0)  )
                    AddEdge(i,j+N,-C[i]*C[j],INF);    
        }
    }
    Liu::MCMF();
}
main()
{
    #ifdef WIN32
    freopen("a.in","r",stdin);
    #else
    #endif
    memset(head,-1,sizeof(head));
    N=read();
    for(int i=1;i<=N;i++) A[i]=read();
    for(int i=1;i<=N;i++) B[i]=read();
    for(int i=1;i<=N;i++) C[i]=read();
    Work();
    return 0;
}

 

相关文章:

  • Leetcode PHP题解--D10 942. DI String Match
  • Java学习笔记之ArrayList基本用法
  • 阿里巴巴2020届校招实习生内推开始啦
  • ionic3 学习记录
  • 【虾说区块链】搞懂P2P网络,再谈区块链!P2P网络概念扫盲帖
  • 三、分别用for、while、do-while、循环语句以及递归方法计算n!,并输出算式。
  • sitemap
  • 【383】defaultdict 相关用法
  • spring cloud(三):Eureka服务的搭建
  • 一个linux 驱动升级的小问题记录
  • Electron Cash钱包如何离线转BCH
  • Redux小结
  • 2017年360最后一道编程题
  • 翻译:CREATE PROCEDURE语句(已提交到MariaDB官方手册)
  • 智能手机拍照进化论:从传感器到算法摄影
  • 《Java8实战》-第四章读书笔记(引入流Stream)
  • 【跃迁之路】【641天】程序员高效学习方法论探索系列(实验阶段398-2018.11.14)...
  • Apache的基本使用
  • Asm.js的简单介绍
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • java8 Stream Pipelines 浅析
  • js中forEach回调同异步问题
  • node-glob通配符
  • Python爬虫--- 1.3 BS4库的解析器
  • REST架构的思考
  • 技术攻略】php设计模式(一):简介及创建型模式
  • 融云开发漫谈:你是否了解Go语言并发编程的第一要义?
  • 删除表内多余的重复数据
  • hi-nginx-1.3.4编译安装
  • raise 与 raise ... from 的区别
  • Semaphore
  • 容器镜像
  • ​ ​Redis(五)主从复制:主从模式介绍、配置、拓扑(一主一从结构、一主多从结构、树形主从结构)、原理(复制过程、​​​​​​​数据同步psync)、总结
  • #etcd#安装时出错
  • #Z2294. 打印树的直径
  • (07)Hive——窗口函数详解
  • (2022 CVPR) Unbiased Teacher v2
  • (C)一些题4
  • (javascript)再说document.body.scrollTop的使用问题
  • (zt)基于Facebook和Flash平台的应用架构解析
  • (六)什么是Vite——热更新时vite、webpack做了什么
  • (三维重建学习)已有位姿放入colmap和3D Gaussian Splatting训练
  • (一)为什么要选择C++
  • (转)eclipse内存溢出设置 -Xms212m -Xmx804m -XX:PermSize=250M -XX:MaxPermSize=356m
  • .gitignore
  • .gitignore文件—git忽略文件
  • .NET 4.0中的泛型协变和反变
  • .net core 调用c dll_用C++生成一个简单的DLL文件VS2008
  • .net mvc 获取url中controller和action
  • .NET 解决重复提交问题
  • .Net开发笔记(二十)创建一个需要授权的第三方组件
  • /dev/sda2 is mounted; will not make a filesystem here!
  • [@Controller]4 详解@ModelAttribute
  • [20171113]修改表结构删除列相关问题4.txt
  • [Android]RecyclerView添加HeaderView出现宽度问题