Luogu P4068 [SDOI2016]数字配对
反正现在做题那么少就争取做一题写一题博客吧
看到题目发现数字种类不多,而且结合价值的要求可以容易地想到使用费用流
但是我们如果朴素地建图就会遇到一个问题,若\(i,j\)符合要求,那么给\(i,j\)连的应该是双向边,但双向边怎么跑网络流?
所以我们就要考虑怎么给边定向,我们稍加观察就会发现如果\(i,j\)合法,\(j,k\)也合法,那么\(i,k\)显然是不合法的(分四类情况讨论一下都是不合法的)
考虑那个整除出一个质数的条件,我们发现如果我们定义\(ct_i\)为\(a_i\)的所有质因数的指数之和
那么\(i,j\)满足条件当且仅当\((ct_i=ct_j+1\and a_j|a_i)\or(ct_j=ct_i+1\and a_i|a_j)\),这样一来我们就可以解释上面\(i,j,k\)三者的关系了
那么我们发现在有了\(ct_i\)之后我们就可以把数字分在两边,左边放奇数,右边放偶数,这样就构成了一个二分图,我们只从左边向右边连边即可
然后注意一下我们用EK跑最小费用最大流时每一次增广求出的最长路一定不会大于上一次增广求出的最长路,因此直接按顺序累加即可,注意最后一次的特判,详见代码
#include<cstdio>
#include<queue>
#include<iostream>
#define int long long
#define RI register int
#define CI const int&
using namespace std;
const int N=205,INF=1e18;
struct edge
{
int to,nxt,v,c;
}e[N*N<<2]; int n,head[N],s,t,cnt=1,a[N],b[N],c[N],ct[N];
inline int resolve(int x,int ret=0)
{
for (RI i=2;i*i<=x;++i) while (x%i==0) ++ret,x/=i; return ret+(x>1);
}
class Network_Flow
{
private:
queue <int> q; int dis[N],pre[N],lst[N],cap[N]; bool vis[N];
#define to e[i].to
inline bool SPFA(CI s,CI t)
{
RI i; for (i=s;i<=t;++i) dis[i]=-INF; q.push(s);
cap[s]=INF; dis[s]=0; while (!q.empty())
{
int now=q.front(); vis[now]=0; q.pop();
for (i=head[now];i;i=e[i].nxt)
if (e[i].v&&dis[now]+e[i].c>dis[to])
{
dis[to]=dis[pre[to]=now]+e[lst[to]=i].c;
if (cap[to]=min(cap[now],e[i].v),!vis[to]) q.push(to),vis[to]=1;
}
}
return dis[t]!=-INF;
}
#undef to
public:
inline void addedge(CI x,CI y,CI v,CI c)
{
e[++cnt]=(edge){y,head[x],v,c}; head[x]=cnt;
e[++cnt]=(edge){x,head[y],0,-c}; head[y]=cnt;
}
inline int solve(CI s,CI t)
{
int ret=0,ans=0; while (SPFA(s,t))
{
if (ret+dis[t]*cap[t]>=0)
{
ret+=dis[t]*cap[t]; ans+=cap[t];
for (int nw=t;nw!=s;nw=pre[nw])
e[lst[nw]].v-=cap[t],e[lst[nw]^1].v+=cap[t];
} else return ans+ret/(-dis[t]);
}
return ans;
}
}NF;
signed main()
{
RI i,j; for (scanf("%lld",&n),i=1;i<=n;++i) scanf("%lld",&a[i]),ct[i]=resolve(a[i]);
for (i=1;i<=n;++i) scanf("%lld",&b[i]); for (i=1;i<=n;++i) scanf("%lld",&c[i]);
for (t=n+1,i=1;i<=n;++i) if (ct[i]&1) NF.addedge(s,i,b[i],0); else NF.addedge(i,t,b[i],0);
for (i=1;i<=n;++i) if (ct[i]&1) for (j=1;j<=n;++j) if (!(ct[j]&1))
if ((ct[i]+1==ct[j]&&a[j]%a[i]==0)||(ct[j]+1==ct[i]&&a[i]%a[j]==0))
NF.addedge(i,j,INF,c[i]*c[j]); return printf("%lld",NF.solve(s,t)),0;
}
Luogu P4068 [SDOI2016]数字配对的更多相关文章
- p4068 [SDOI2016]数字配对
传送门 分析 我们考虑对所有a[i]质因数分解,然后记cnt[i]为a[i]是由几个质数相乘得到的 然后我们建一个二分图,左面为所有cnt[i]为奇数的点,右面是为偶数的点 我们从源点向左面点连容量b ...
- 图论(费用流):BZOJ 4514 [Sdoi2016]数字配对
4514: [Sdoi2016]数字配对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 820 Solved: 345[Submit][Status ...
- BZOJ 4514: [Sdoi2016]数字配对 [费用流 数论]
4514: [Sdoi2016]数字配对 题意: 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数 ...
- 【bzoj4514】: [Sdoi2016]数字配对 图论-费用流
[bzoj4514]: [Sdoi2016]数字配对 好像正常的做法是建二分图? 我的是拆点然后 S->i cap=b[i] cost=0 i'->T cap=b[i] cost=0 然后 ...
- BZOJ 4514: [Sdoi2016]数字配对
4514: [Sdoi2016]数字配对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1606 Solved: 608[Submit][Statu ...
- 【BZOJ4514】[Sdoi2016]数字配对 费用流
[BZOJ4514][Sdoi2016]数字配对 Description 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ...
- BZOJ4514——[Sdoi2016]数字配对
有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×cj 的 ...
- bzoj4514 [Sdoi2016]数字配对
Description 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对 ...
- BZOJ4514[Sdoi2016]数字配对——最大费用最大流
题目描述 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci ...
随机推荐
- The Three Rules/Laws of TDD
You are not allowed to write any production code unless it is to make a failing unit test pass. 除非为了 ...
- 用OC基于数组实现循环队列
一.简言 使用数组实现循环队列时,始终会有一个空余的位置预留着,作为一个判决队列已满的条件(当然也可以采用其他方式).在前面已经用C++介绍了基本的算法,可以去回顾一下https://www.cnbl ...
- 为什么不允许使用 Java 静态构造函数?
不允许使用 Java 静态构造函数,但是为什么呢?在深入探讨不允许使用静态构造函数的原因之前,让我们看看如果要使 构造函数静态化 会发生什么. Java 静态构造函数 假设我们有一个定义为的类: pu ...
- tomcat程序生成的日志文件不可读问题 - 运维总结
现象描述:线上机器的程序文件(包括TOMCAT自身)使用APP账号作为属主运行,同时禁止了APP账号的BASH.登录系统使用了统一认证,这样每个人都有自己的账号登录系统.为了方便开发人员登录查看日志, ...
- sed命令:删除匹配行和替换
删除以a开头的行 sed -i '/^a.*/d' tmp.txt -i 表示操作在源文件上生效.否则操作内存中数据,并不写入文件中.在分号内的/d表示删除匹配的行 替换匹配行: sed -i 's/ ...
- 深入理解java中的byte类型
作者 | 进击的石头--GO! 来源 | https://www.cnblogs.com/zl181015/p/9435035.html#4432849 Java也提供了一个byte数据类型,并且是基 ...
- Swagger UI in AspNetCore WebAPI
Swagger其实包含了三个部分,分别是Swagger Editor文档接口编辑器,根据接口文档生成code的Swagger Codegen,以及生成在线文档的Swagger UI.在AspNetCo ...
- Javase之多线程(1)
多线程(1) 多线程的概述 了解多线程之前需要先了解线程,而线程依赖于进程而存在,所以先了解进程. 什么是进程 进程就是正在运行的程序.是系统进行资源分配和调用的独立单位.每一个进程都有它自己的内存空 ...
- Windows下 gcc/g++的安装与配置
引言 我们知道开发最好用Mac/Linux,效率很高,但是对于很多还是Windows用户的我们来说,编写代码再到linux上运行也是很常有的事情,但对于我们写一些小demo使用上面的流程难免有点兴师动 ...
- java报错问题记录
java.lang.NoSuchMethodError 运行时错误,再编译期一般不会出现这个问题.NoSuchMethodError中文意思是没有找到方法,遇到这个错误并不是说依赖的jar包.方法不存 ...