4514: [Sdoi2016]数字配对

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 726  Solved: 309
[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上传

Solution

二分图建图方式,分析一下

如果$a[i]$和$a[j]$互质,不妨把它们分解质因子,互质即质因子约去后的质因子互质,或者只剩一个质因子

所以考虑先预处理 线性筛质数,再质因数分解,含有奇数个质因子的与含有偶数个质因子的分列两排

如果满足$a[i]$和$a[j]$可连($a[i]$为质因数为奇的$a[j]$为质因数为偶的),则由$i--->j$连容量$inf$,费用$c[i]*c[j]$

由$S--->odd[i]$连容量$b[odd[i]]$,费用为$0$;同理$even[i]--->T$连容量$b[even[i]]$费用$0$

然后跑最大费用最大流,因为最大费用最大流每次增广的路径费用严格不下降,所以,贪心的一直跑到总费用$<=0$的时候,单独判断一下即可

容易出问题的细节:

1.注意开longlong...

2.Inf的范围要注意(习惯性的开0x7fffffff导致WA5组...)

3.不能暴力筛和暴力分解,时间复杂度不科学

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define maxn 1010
#define maxm 100010
int n,a[maxn],b[maxn];long long c[maxn]; bool f=;
struct EdgeNode{int next,cap,to,from;long long cost;}edge[maxm];
int head[maxn],cnt=;
void add(int u,int v,int w,long long c)
{
cnt++;
edge[cnt].to=v;edge[cnt].from=u;edge[cnt].cap=w;edge[cnt].cost=c;edge[cnt].next=head[u];head[u]=cnt;
}
void insert(int u,int v,int w,long long c) {add(u,v,w,c); add(v,u,,-c);}
int from[maxn],S,T; long long dis[maxn]; bool mark[maxn];
#define inf 10000000000000LL
bool spfa()
{
queue<int>q;
for (int i=S; i<=T; i++) dis[i]=-inf; memset(from,,sizeof(from));
q.push(S); mark[S]=; dis[S]=;
while (!q.empty())
{
int now=q.front(); q.pop(); mark[now]=;
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].cap && dis[edge[i].to]<dis[now]+edge[i].cost)
{
dis[edge[i].to]=dis[now]+edge[i].cost; from[edge[i].to]=i;
if (!mark[edge[i].to])
q.push(edge[i].to),mark[edge[i].to]=;
}
}
return dis[T]!=-inf;
}
long long Cost; int Flow;
void MaxCostFlow()
{
int flow=inf;
for (int i=from[T]; i; i=from[edge[i].from])
flow=min(flow,edge[i].cap); if ((long long)Cost+flow*dis[T]>=0LL)
{
for (int i=from[T]; i; i=from[edge[i].from])
edge[i].cap-=flow,edge[i^].cap+=flow;
Flow+=flow; Cost+=dis[T]*flow; }
else
Flow+=abs(Cost/dis[T]),Cost-=(Cost/dis[T])*dis[T],f=;
// Flow+=flow;
//printf("%d %I64d %I64d\n",Flow,Cost,dis[T]);
}
int prime[],tot; bool flag[];
void Prework()
{
flag[]=;
for (int i=; i<=; i++)
{
if (!flag[i]) prime[++tot]=i;
for (int j=; j<=tot&&i*prime[j]<=; j++)
flag[i*prime[j]]=;
}
}
int odd[maxn],even[maxn],ot,et;
bool check(int x,int y)
{
if (x%y && y%x || !x || !y) return ;
int tmp=max(x/y,y/x);
for (int i=; i<=tot&&prime[i]<tmp; i++)
if (tmp%prime[i]==) return ;
return ;
}
void Build()
{
Prework();
S=,T=n+;
for (int i=,ct=; i<=n; i++,ct=)
{
for (int j=,tmp=a[i]; j<=tot; j++,tmp=a[i])
while (tmp%prime[j]==) tmp/=prime[j],ct++;
//else if (prime[j]>tmp) break;
if (ct&) odd[++ot]=i; else even[++et]=i;
}
for (int i=; i<=ot; i++)
for (int j=; j<=et; j++)
if (check(a[odd[i]],a[even[j]]))
insert(odd[i],even[j],inf,c[odd[i]]*c[even[j]])/*,printf("%d-->%d:%d/%I64d\n",odd[i],even[j],inf,c[odd[i]]*c[even[j]])*/;
for (int i=; i<=ot; i++) insert(S,odd[i],b[odd[i]],0LL)/*,printf("%d-->%d:%d/%I64d\n",S,odd[i],b[odd[i]],0LL)*/;
for (int i=; i<=et; i++) insert(even[i],T,b[even[i]],0LL)/*,printf("%d-->%d:%d/%I64d\n",even[i],T,b[even[i]],0LL)*/;
//printf("%d %d %d\n",ot,et,cnt);
}
int main()
{
// freopen("menci_pair.in","r",stdin);
// freopen("menci_pair.out","w",stdout);
n=read();
for (int i=; i<=n; i++) a[i]=read();
for (int i=; i<=n; i++) b[i]=read();
for (int i=; i<=n; i++) c[i]=(long long)read();
Build();
while (spfa() && !f) MaxCostFlow();
printf("%d\n",Flow);
return ;
}

当时唯一想出和出题人一模一样的解法的题,但是最后不知道莫名其妙的写错了什么地方,结果连暴力分都不到....(回来之后这么久才想起来重写一遍..)

【BZOJ-4514】数字配对 最大费用最大流 + 质因数分解 + 二分图 + 贪心 + 线性筛的更多相关文章

  1. BZOJ4514[Sdoi2016]数字配对——最大费用最大流

    题目描述 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci ...

  2. bzoj 4514: 数字配对

    题目大意 自己看 题解 我们打表观察规律发现一定能构成一张二分图 也就是不存在奇环 所以我们一般保证费用非负的最大流即可. #include <cstdio> #include <c ...

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

    [bzoj4514]: [Sdoi2016]数字配对 好像正常的做法是建二分图? 我的是拆点然后 S->i cap=b[i] cost=0 i'->T cap=b[i] cost=0 然后 ...

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

    题目 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×c ...

  5. bzoj4514: [Sdoi2016]数字配对(费用流)

    传送门 ps:费用流增广的时候费用和流量打反了……调了一个多小时 每个数只能参与一次配对,那么这就是一个匹配嘛 我们先把每个数分解质因数,记质因子总个数为$cnt_i$,那如果$a_i/a_j$是质数 ...

  6. BZOJ 1927 星际竞速(最小费用最大流)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1927 题意:一个图,n个点.对于给出的每条边 u,v,w,表示u和v中编号小的那个到编号 ...

  7. BZOJ 2424: [HAOI2010]订货(最小费用最大流)

    最小费用最大流..乱搞即可 ------------------------------------------------------------------------------ #includ ...

  8. 【BZOJ4514】数字配对(费用流)

    题意: 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci× ...

  9. [SDOI2016]数字配对(费用流+贪心+trick)

    重点是如何找到可以配对的\(a[i]\)和\(a[j]\). 把\(a[i]\)分解质因数.设\(a[i]\)分解出的质因数的数量为\(cnt[i]\). 设\(a[i]\geq a[j]\) 那么\ ...

随机推荐

  1. Java命令行的执行参数

    Java 程序命令行参数说明 启动Java程序的方式有两种: # starts a Java virtual machine, loads the specified class, and invok ...

  2. POJ 3714 Raid

    Description After successive failures in the battles against the Union, the Empire retreated to its ...

  3. 基于LeNet网络的中文验证码识别

    基于LeNet网络的中文验证码识别 由于公司需要进行了中文验证码的图片识别开发,最近一段时间刚忙完上线,好不容易闲下来就继上篇<基于Windows10 x64+visual Studio2013 ...

  4. Integer.valueof(null)报错

    原文  http://javacat360.iteye.com/blog/2024378 主题 Java 昨天,一同事问我一个问题,估计是他前段日子面试遇到的 问题很简单,String.valueof ...

  5. 关于div标签的title属性一闪一闪不正常显示的原因

    弹出了chrome的开发工具就会出现以上问题.

  6. node基础07:写文件

    1.writeFile //server.js var http = require("http"); var writefile = require("./writef ...

  7. weblogic.nodemanager.common.ConfigException: Native version is enabled but nodemanager native library could not be loaded 解决办法

    近日在一个原本工作正常的weblogic web server(操作系统为redhat 64位系统)上折腾安装redis/hadoop等东东,yum install了一堆第3方类库后,重启weblog ...

  8. TinyFrame续篇:整合Spring IOC实现依赖注入

    上一篇主要讲解了如何搭建基于CodeFirst的ORM,并且在章节末我们获取了上下文对象的实例:BookContext.这节主要承接上一篇,来讲解如何整合Spring IOC容器实现控制反转,依赖注入 ...

  9. Working Set缓存算法(转)

    为了加深对缓存算法的理解,特转此篇,又由于本文内容过多,故不做翻译,原文地址Working Set页面置换算法 In the purest form of paging, processes are ...

  10. 极简Word排版示例(以Word2013为例)

    文档标题 第一行写下文档的名字,居中,微软雅黑字体,三号 章节标题 每一章的标题单独一行,光标选中这行,设置为标题1 每一节的标题单独一行,光标选中这行,设置为标题2 全部章节标题设置完毕后,下一步 ...