bzoj4514 [Sdoi2016]数字配对
Description
Input
Output
一行一个数,最多进行多少次配对
Sample Input
2 4 8
2 200 7
-1 -2 1
Sample Output
HINT
n≤200,ai≤10^9,bi≤10^5,∣ci∣≤10^5
正解:费用流。
这题的费用流模型还是比较显然的,不过有两个要注意的地方。
首先这题需要建成二分图的模型,所以每个点的流量肯定会乘$2$,如果直接连可能会导致有些点多用了流量。对于这种情况,我们在每个$i->j$的连边时,把$j->i$也连边,最后把流量除以$2$,就能解决这个问题了。
还有一个问题,题目是问的费用$>=0$的最大流,首先我们肯定要把费用取反,转成最小费用最大流。然后我们可以在每次增广时加一个特判,如果之前增广的费用+当前费用$>0$,那么我们直接取使得费用$<=0$的最大流量就行了。因为费用流每次都是找最短路增广,所以这样做是对的。
- //It is made by wfj_2048~
- #include <algorithm>
- #include <iostream>
- #include <complex>
- #include <cstring>
- #include <cstdlib>
- #include <cstdio>
- #include <vector>
- #include <cmath>
- #include <queue>
- #include <stack>
- #include <map>
- #include <set>
- #define inf (1LL<<60)
- #define N (3010)
- #define il inline
- #define RG register
- #define ll long long
- #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
- using namespace std;
- struct edge{ ll nt,to,flow,cap,dis; }g[];
- ll head[N],dis[N],vis[N],f[N],p[N],fa[N],a[N],b[N],c[N];
- ll q[],n,S,T,flow,cost,num=;
- il ll gi(){
- RG ll x=,q=; RG char ch=getchar();
- while ((ch<'' || ch>'') && ch!='-') ch=getchar();
- if (ch=='-') q=-,ch=getchar();
- while (ch>='' && ch<='') x=x*+ch-,ch=getchar();
- return q*x;
- }
- il void insert(RG ll from,RG ll to,RG ll cap,RG ll cost){
- g[++num]=(edge){head[from],to,,cap,cost},head[from]=num; return;
- }
- il ll bfs(RG ll S,RG ll T){
- for (RG ll i=;i<=T;++i) dis[i]=inf;
- RG ll h=,t=; q[t]=S,dis[S]=,vis[S]=,f[S]=inf;
- while (h<t){
- RG ll x=q[++h],v;
- for (RG ll i=head[x];i;i=g[i].nt){
- v=g[i].to;
- if (dis[v]>dis[x]+g[i].dis && g[i].cap>g[i].flow){
- dis[v]=dis[x]+g[i].dis,fa[v]=x,p[v]=i;
- f[v]=min(f[x],g[i].cap-g[i].flow);
- if (!vis[v]) vis[v]=,q[++t]=v;
- }
- }
- vis[x]=;
- }
- if (dis[T]==inf) return ;
- if (cost+dis[T]*f[T]>){ //费用>0特判
- RG ll x=-cost/dis[T];
- flow+=x; return ;
- }
- flow+=f[T],cost+=dis[T]*f[T];
- for (RG ll i=T;i!=S;i=fa[i])
- g[p[i]].flow+=f[T],g[p[i]^].flow-=f[T];
- return ;
- }
- il ll isprime(RG ll x){
- if (x== || x==) return ;
- if (!(x&)) return x==;
- for (RG ll i=;i*i<=x;++i)
- if (!(x%i)) return ;
- return ;
- }
- il void work(){
- n=gi(),S=*n+,T=*n+;
- for (RG ll i=;i<=n;++i) a[i]=gi();
- for (RG ll i=;i<=n;++i) b[i]=gi();
- for (RG ll i=;i<=n;++i) c[i]=gi();
- for (RG ll i=;i<=n;++i){
- insert(S,i,b[i],),insert(i,S,,);
- insert(n+i,T,b[i],),insert(T,n+i,,);
- }
- for (RG ll i=;i<=n;++i)
- for (RG ll j=;j<=n;++j){
- if (a[i]%a[j]) continue;
- if (isprime(a[i]/a[j])){
- insert(i,n+j,inf,-c[i]*c[j]),insert(n+j,i,,c[i]*c[j]);
- insert(j,n+i,inf,-c[i]*c[j]),insert(n+i,j,,c[i]*c[j]);
- //防止多余流量影响结果
- }
- }
- while (bfs(S,T)); printf("%lld\n",flow>>); return;
- }
- int main(){
- File("match");
- work();
- return ;
- }
bzoj4514 [Sdoi2016]数字配对的更多相关文章
- BZOJ4514——[Sdoi2016]数字配对
有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×cj 的 ...
- BZOJ4514[Sdoi2016]数字配对——最大费用最大流
题目描述 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci ...
- bzoj4514 [Sdoi2016]数字配对(网络流)
Description 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对 ...
- [bzoj4514][SDOI2016]数字配对——二分图
题目描述 传送门 题解: 这个题真的是巨坑,经过了6个WA,2个TLE,1个RE后才终于搞出来,中间都有点放弃希望了... 主要是一定要注意longlong! 下面开始说明题解. 朴素的想法是: 如果 ...
- BZOJ4514 [Sdoi2016]数字配对 【费用流】
题目 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×c ...
- bzoj4514: [Sdoi2016]数字配对--费用流
看了一眼题目&数据范围,觉得应该是带下界的费用流 原来想拆点变成二分图,能配对的连边,跑二分图,可行性未知 后来看到另外一种解法.. 符合匹配要求的数要满足:质因子的个数相差为1,且两者可整除 ...
- bzoj4514: [Sdoi2016]数字配对(费用流)
传送门 ps:费用流增广的时候费用和流量打反了……调了一个多小时 每个数只能参与一次配对,那么这就是一个匹配嘛 我们先把每个数分解质因数,记质因子总个数为$cnt_i$,那如果$a_i/a_j$是质数 ...
- 【bzoj4514】: [Sdoi2016]数字配对 图论-费用流
[bzoj4514]: [Sdoi2016]数字配对 好像正常的做法是建二分图? 我的是拆点然后 S->i cap=b[i] cost=0 i'->T cap=b[i] cost=0 然后 ...
- 【BZOJ4514】[Sdoi2016]数字配对 费用流
[BZOJ4514][Sdoi2016]数字配对 Description 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ...
随机推荐
- 用虚拟机安装Linux系统的过程
1.打开VMware->点击File->点击New Virtual Machine.. 2.我们选择Custom并点击Next 3.保持默认然后点next 4.选择图中所示内容,点Next ...
- HTML5学习笔记<四>: 列表, 块和布局
HTML列表 列表标签 标签 描述 <ol> 定义有序列表. <ul> 定义无序列表. <li> 定义列表项. <dl> 定义定义列表. <dt& ...
- 学学简单的-------------javaScript基础
首先知道什么是JavaScript? JavaScript是一种描述性语言,也是一种基于对象和事件驱动的.并具有安全性的脚本语言. 2.JavaScript由三部分组成:①ecmascript ②Bo ...
- 图解Javascript——变量对象和活动对象
span { line-height: 1.5 } 这是由一段代码引发的思考: var laterDeclaredVar = 'I am a global variable ...'; (functi ...
- spring项目中dubbo相关的配置文件出现红叉的问题
近来在eclipse中导入了一个web项目,但是发现项目上有红色的叉号. 原来是spring中关于dubbo的配置文件报错了. Multiple annotations found at this l ...
- docker工作流程
Docker提供一种方法在容器中运行安全隔离的应用程序,应用程序与所有依赖项和库一起打包在容器中.因为你的应用程序总是可以使用它在构建镜像中期望的环境运行,测试和部署比以往任何时候都更简单,因为你的构 ...
- 常见排序算法-Python实现
常见排序算法-Python实现 python 排序 算法 1.二分法 python 32行 right = length- : ] ): test_list = [,,,,,, ...
- 任务一:零基础HTML编码练习
任务目的 了解HTML的定义.概念.发展简史 掌握常用HTML标签的含义.用法 能够基于设计稿来合理规划HTML文档结构 理解语义化,合理地使用HTML标签来构建页面 任务描述:完成一个HTML页面代 ...
- 老李推荐:第1章2节《MonkeyRunner源码剖析》概述:边界
老李推荐:第1章2节<MonkeyRunner源码剖析>概述:边界 边界 怎么样才算分析清楚一个事物的原理是什么呢?就以前面提到的<LINUX内核源代码情景分析>为例子,分 ...
- 【R.转载】apply函数族的使用方法
为什么用apply 因为我是一个程序员,所以在最初学习R的时候,当成"又一门编程语言"来学习,但是怎么学都觉得别扭.现在我的看法倾向于,R不是一种通用型的编程语言,而是一种统计领域 ...