BZOJ4514 [Sdoi2016]数字配对 【费用流】
题目
有 n 种数字,第 i 种数字是 ai、有 bi 个,权值是 ci。
若两个数字 ai、aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数,
那么这两个数字可以配对,并获得 ci×cj 的价值。
一个数字只能参与一次配对,可以不参与配对。
在获得的价值总和不小于 0 的前提下,求最多进行多少次配对。
输入格式
第一行一个整数 n。
第二行 n 个整数 a1、a2、……、an。
第三行 n 个整数 b1、b2、……、bn。
第四行 n 个整数 c1、c2、……、cn。
输出格式
一行一个数,最多进行多少次配对
输入样例
3
2 4 8
2 200 7
-1 -2 1
输出样例
4
提示
n≤200,ai≤109,bi≤105,∣ci∣≤10^5
题解
如果\(a_i\)和\(a_j\)之间相差一个质数,那么它们一定是互为倍数关系且质因子分解后指数和只相差\(1\)
容易发现,相互匹配的两个数的指数和一定是一奇一偶
所以这是一个二分图匹配问题
用最大费用最大流实现匹配即可
但由于费用和非负,我们在最大流统计流量时,如果当前答案加上本次新增费用小于0,就刚好取到不小于0的部分
由于先取大的一定比取小的好,所以这样的贪心策略正确
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
using namespace std;
const int maxn = 205,maxm = 200005;
const LL INF = 1000000000000000000ll;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int n,ans;
LL a[maxn],b[maxn],c[maxn],cnt[maxn],sum;
LL d[maxn],minf[maxn];
int p[maxn];
int h[maxn],ne = 2,S,T;
struct EDGE{int to,nxt; LL f,w;}ed[maxm];
inline void build(int u,int v,LL f,LL w){
ed[ne] = (EDGE){v,h[u],f,w}; h[u] = ne++;
ed[ne] = (EDGE){u,h[v],0,-w}; h[v] = ne++;
}
void Sp(int u){
int x = a[u];
for (int i = 2; i <= x; i++)
if (x % i == 0){
while (x % i == 0) cnt[u]++,x /= i;
}
if (x - 1) cnt[u]++;
}
queue<int> q;
int inq[maxn];
void mincost(){
while (true){
for (int i = S; i <= T; i++) inq[i] = p[i] = 0,d[i] = INF;
q.push(S); d[S] = 0; minf[S] = INF;
int u;
while (!q.empty()){
u = q.front(); q.pop();
inq[u] = false;
Redge(u) if (ed[k].f && d[to = ed[k].to] > d[u] + ed[k].w){
d[to] = d[u] + ed[k].w; minf[to] = min(minf[u],ed[k].f);
p[to] = k;
if (!inq[to]) q.push(to),inq[to] = true;
}
}
if (d[T] == INF) return;
if (d[T] <= 0){
sum += -d[T] * minf[T];
ans += minf[T];
u = T;
while (u != S){
ed[p[u]].f -= minf[T];
ed[p[u] ^ 1].f += minf[T];
u = ed[p[u] ^ 1].to;
}
}
else {
int l = min(minf[T],sum / d[T]);
if (!l) return;
sum += -d[T] * l;
ans += l;
u = T;
while (u != S){
ed[p[u]].f -= l;
ed[p[u] ^ 1].f += l;
u = ed[p[u] ^ 1].to;
}
}
}
}
int main(){
n = read(); S = 0; T = n + 1;
REP(i,n) a[i] = read(),Sp(i);
REP(i,n){
b[i] = read();
if (cnt[i] & 1) build(S,i,b[i],0);
else build(i,T,b[i],0);
}
REP(i,n) c[i] = read();
REP(i,n) REP(j,n){
if ((cnt[i] & 1) && !(cnt[j] & 1) && ((a[i] % a[j] == 0 && cnt[i] == cnt[j] + 1) || (a[j] % a[i] == 0 && cnt[j] == cnt[i] + 1))){
build(i,j,INF,-(c[i] * c[j]));
}
}
mincost();
printf("%d\n",ans);
return 0;
}
BZOJ4514 [Sdoi2016]数字配对 【费用流】的更多相关文章
- bzoj4514: [Sdoi2016]数字配对--费用流
看了一眼题目&数据范围,觉得应该是带下界的费用流 原来想拆点变成二分图,能配对的连边,跑二分图,可行性未知 后来看到另外一种解法.. 符合匹配要求的数要满足:质因子的个数相差为1,且两者可整除 ...
- 【BZOJ4514】[Sdoi2016]数字配对 费用流
[BZOJ4514][Sdoi2016]数字配对 Description 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ...
- BZOJ 4514: [Sdoi2016]数字配对 [费用流 数论]
4514: [Sdoi2016]数字配对 题意: 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数 ...
- BZOJ.4514.[SDOI2016]数字配对(费用流SPFA 二分图)
BZOJ 洛谷 \(Solution\) 很显然的建二分图后跑最大费用流,但有个问题是一个数是只能用一次的,这样二分图两部分都有这个数. 那么就用两倍的.如果\(i\)可以向\(j'\)连边,\(j\ ...
- 【BZOJ 4514】[Sdoi2016]数字配对 费用流
利用spfa流的性质,我直接拆两半,正解分奇偶(妙),而且判断是否整除且质数我用的是暴力根号,整洁判断质数个数差一(其他非spfa流怎么做?) #include <cstdio> #inc ...
- 4514: [Sdoi2016]数字配对 费用流
链接 https://www.lydsy.com/JudgeOnline/problem.php?id=4514 思路 EK直接贪心做 <0的时候加上剩余返回 二分图a->b的时候 把b- ...
- BZOJ4514[Sdoi2016]数字配对——最大费用最大流
题目描述 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci ...
- 【BZOJ4514】【SDOI2016】数字配对 [费用流]
数字配对 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description 有 n 种数字,第 i 种数字是 ...
- bzoj4514: [Sdoi2016]数字配对(费用流)
传送门 ps:费用流增广的时候费用和流量打反了……调了一个多小时 每个数只能参与一次配对,那么这就是一个匹配嘛 我们先把每个数分解质因数,记质因子总个数为$cnt_i$,那如果$a_i/a_j$是质数 ...
- [bzoj4514]数字配对[费用流]
今年SDOI的题,看到他们在做,看到过了一百多个人,然后就被虐惨啦... 果然考试的时候还是打不了高端算法,调了...几天 默默地yy了一个费用流构图: 源连所有点,配对的点连啊,所有点连汇... 后 ...
随机推荐
- 谷歌浏览器 加安全地址 快捷方式加参数 chrome
--unsafely-treat-insecure-origin-as-secure="http://192.168.43.17:8080"
- 在DataGridView控件中启用换行
实现效果: 知识运用: DataGridView控件公共属性DefaultCellStyle的WrapMode属性 public DataGridViewTriState WrapMode { ge ...
- JavaScript -- 内置对象字符串
charAt和charCodeAt charAt语法: stringObject.charAt(index) 功能: 返回stringObject中index位置的字符. charCodeAt语法 s ...
- Dojo操作dom元素的样式
1.使用dom-style的set方法,可以直接设置dom元素的样式属性,这和使用dom元素的style属性效果一样. 2.使用dom-class的replace方法可以替换某个dom元素的样式,ad ...
- 作业题:闰年 if((year%4==0&&year%100!=0)||year&400==0)
作业题:闰年 if((year%4==0&&year%100!=0)||year&400==0)
- mysql锁机制(转载)
锁是计算机协调多个进程或线程并发访问某一资源的机制 .在数据库中,除传统的 计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是所 ...
- 标准C++(2)
一.类 C++是一种面向对象的语言,它在C语言的基础上添加了一种新的数据结构,类 ——class class是一种复合型的数据结构 它能够由不同类型的变量及函数组成 C++中的class与struct ...
- zoj 4049
Halting Problem Time Limit: 1 Second Memory Limit: 65536 KB In computability theory, the haltin ...
- Centos7重启网卡失败解决方法
service Network-Manager stop 执行命令解决,如果执行命令还是失败,则是配置文件内容的问题,检查配置文件
- jmeter中重要组件及其执行顺序
jmeter中重要组件有:Sampler,计时器,前置处理器和后置处理器,断言,Controller,Listener和配置原件. 同类组件之间是从上到下的顺序执行,不同组件之间是按照以下的顺序执行的 ...