[SDOI2016 Round1] 数字配对
COGS 2221. [SDOI2016 Round1] 数字配对
http://www.cogs.pro/cogs/problem/problem.php?pid=2221
★★★ 输入文件:menci_pair.in
输出文件:menci_pair.out
简单对比
时间限制:1 s 内存限制:128 MB
【题目描述】
有 n 种数字,第 i 种数字是 ai、有 bi 个,权值是 ci。
若两个数字 ai、aj 满足,ai 是 aj 的倍数,且 aiaj 是一个质数,那么这两个数字可以配对,并获得 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
【提示】
测试点 1 ~ 3:n≤10,ai≤109,bi=1,∣ci∣≤105;
测试点 4 ~ 5:n≤200,ai≤109,bi≤105,ci=0;
测试点 6 ~ 10:n≤200,ai≤109,bi≤105,∣ci∣≤105。
【来源】
SDOI2016 Round1 Day1
费用流u
构图方法:(以样例为例)
1、2可以配对;2、3可以配对
注意,这里若a与b可以配对,则既要由a向b连边,又要由b向a连同样的边,最后答案除以2
原因:
1、如果只由a向b连,那么如果又有一条边由c连向a,边流量都为inf,这样从源点向a用了,由a向汇点又用了,应该统计的是2次之和,但实际只统计了其中一次
2、a向b连边m、b向a连同样的边n,这样费用流跑m一定跑n,这样就可以把1中2次汇总,因为对应边流量相等,所以答案要除2
因为要总价值和>=0,所以每次跑最大费用,
如果本次跑出的最大价值+已累积的价值>=0,继续跑
反之,次数+已累计价值/-本次单位流量最大费用,结束
因为累计价值不可能为负,而题目要求总价值和>=0,若满足反之条件,本次最大费用<0 且 本次最大费用总和绝对值>已累计价值,所以就看已累计价值最大能抵消多少次本次的负价值
#include<cstdio>
#include<queue>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int a[],b[],c[];
int tot=,src,dec;
int front1[],from[],next1[],to1[];
bool v[];
int n,fa[];
long long dis[],sum_cost,cost[],cap[];
int sum_flow;
queue<int>que;
bool judge(int x)
{
for(int i=;i<=sqrt(x);i++)
if(x%i==) return false;
return true;
}
void insert_edge(int u,int v,long long w,long long val)
{
to1[++tot]=v;from[tot]=u;next1[tot]=front1[u];front1[u]=tot;cap[tot]=w;cost[tot]=val;
to1[++tot]=u;from[tot]=v;next1[tot]=front1[v];front1[v]=tot;cap[tot]=;cost[tot]=-val;
}
bool spfa()
{
for(int i=;i<=dec;i++) dis[i]=-1e15,fa[i]=;
memset(v,,sizeof(v));
que.push(src);v[src]=true;
dis[]=;
while(!que.empty())
{
int now=que.front();
que.pop();v[now]=false;
for(int i=front1[now];i;i=next1[i])
{
if(dis[now]+cost[i]>dis[to1[i]]&&cap[i]>)
{
dis[to1[i]]=dis[now]+cost[i];
fa[to1[i]]=i;
if(!v[to1[i]])
{
que.push(to1[i]);
v[to1[i]]=true;
}
}
}
}
if(dis[dec]!=-1e10) return true;
return false;
}
void work()
{
while(spfa())
{
long long tmp=1e15,k=;
for(int i=fa[dec];i;i=fa[from[i]]) tmp=min(cap[i],tmp);
if(sum_cost+dis[dec]*1ll*tmp>=)
{
sum_cost+=dis[dec]*tmp;sum_flow+=tmp;
for(int i=fa[dec];i;i=fa[from[i]])
{
cap[i]-=tmp;cap[i^]+=tmp;
}
}
else
{
sum_flow+=int(sum_cost/abs(dis[dec]));
break;
}
}
printf("%d",sum_flow/);
return ;
}
int main()
{
freopen("menci_pair.in","r",stdin);
freopen("menci_pair.out","w",stdout);
scanf("%d",&n);
dec=n+<<;
for(int i=;i<=n;i++) scanf("%d",&a[i]);
for(int i=;i<=n;i++) scanf("%d",&b[i]);
for(int i=;i<=n;i++) scanf("%d",&c[i]);
for(int i=;i<=n;i++) insert_edge(src,i<<,b[i],);
for(int i=;i<=n;i++) insert_edge(i<<|,dec,b[i],);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
{
if(a[i]<=a[j]) continue;
if(a[i]%a[j]==&&judge(a[i]/a[j]))
{
insert_edge(j<<,i<<|,1e15,1ll*c[i]*c[j]);
insert_edge(i<<,j<<|,1e15,1ll*c[i]*c[j]);
} }
work();
}
学长说了另外2种方法:
1、根据分解质因数的指数和的奇偶性,将所有点分为2个集合,构建二分图(标解,不想写就没写)
学长AC代码链接:http://www.cnblogs.com/harden/p/6399396.html
2、根据整除关系构成的链,将所有点分为2个集合,每条链的起点在哪个集合里随便,构建二分图,与1不同的地方就是链的起点在哪个集合的问题
(这个写了,然而调了一晚上+半上午,COGS提交最终3A 1W 1RE 5T ,法2正确性、代码正确性有待验证)
#include<cstdio>
#include<queue>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int a[201],b[201],c[201];
int front[210],next[160001],to[160001],tot,src,dec;
int front1[210],from[160001],next1[160001],to1[160001];
bool use_in[210],use_out[210],v[210];
int n,fa[210];
long long dis[210],sum_cost,cost[160001],cap[160001];
int sum_flow;
struct node1
{
int point,id;
};
queue<node1>q;
queue<int>que;
bool judge(int x)
{
for(int i=2;i<=sqrt(x);i++)
if(x%i==0) return false;
return true;
}
void add(int u,int v)
{
to[++tot]=v;next[tot]=front[u];front[u]=tot;
use_in[v]=true;use_out[u]=true;
}
void insert_edge(int u,int v,long long w,long long val)
{
to1[++tot]=v;from[tot]=u;next1[tot]=front1[u];front1[u]=tot;cap[tot]=w;cost[tot]=val;
to1[++tot]=u;from[tot]=v;next1[tot]=front1[v];front1[v]=tot;cap[tot]=0;cost[tot]=-val;
}
bool spfa()
{
for(int i=1;i<=dec;i++) dis[i]=-1e15,fa[i]=0;
que.push(src);v[src]=true;
while(!que.empty())
{
int now=que.front();
que.pop();v[now]=false;
for(int i=front1[now];i;i=next1[i])
{
if(dis[now]+1ll*cost[i]>dis[to1[i]]&&cap[i]>0)
{
dis[to1[i]]=dis[now]+1ll*cost[i];
fa[to1[i]]=i;
if(!v[to1[i]])
{
que.push(to1[i]);
v[to1[i]]=true;
}
}
}
}
if(dis[dec]!=-1e15) return true;
return false;
}
void work()
{
while(spfa())
{
long long tmp=1e15;
for(int i=fa[dec];i;i=fa[from[i]]) tmp=min(cap[i],tmp);
if(sum_cost+dis[dec]*1ll*tmp>=0)
{
sum_cost+=dis[dec]*tmp;sum_flow+=tmp;
for(int i=fa[dec];i;i=fa[from[i]])
{
cap[i]-=tmp;cap[i^1]+=tmp;
}
}
else
{
sum_flow+=int(sum_cost/abs(dis[dec]));
break;
}
}
printf("%d",sum_flow);
return ;
}
int main()
{
freopen("menci_pair.in","r",stdin);
freopen("menci_pair.out","w",stdout);
scanf("%d",&n);
dec=n+1;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) scanf("%d",&b[i]);
for(int i=1;i<=n;i++) scanf("%d",&c[i]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(a[i]<=a[j]) continue;
if(!a[j]) continue;
if(a[i]%a[j]==0&&judge(a[i]/a[j]))
{
add(j,i);
}
}
tot=1;
for(int i=1;i<=n;i++)
if(!use_in[i])
{
insert_edge(src,i,b[i],0);
q.push((node1){i,1});
}
while(!q.empty())
{
node1 now=q.front();q.pop();
for(int i=front[now.point];i;i=next[i])
{
int t=to[i];
if(now.id%2)
{
insert_edge(now.point,t,1e15,1ll*c[now.point]*c[t]);
insert_edge(t,dec,b[t],0);
q.push((node1){t,now.id+1});
}
else
{
insert_edge(t,now.point,1e15,1ll*c[now.point]*c[t]);
insert_edge(src,t,b[t],0);
q.push((node1){t,now.id+1});
}
}
}
work();
}
错误代码
[SDOI2016 Round1] 数字配对的更多相关文章
- Cogs 2221. [SDOI2016 Round1] 数字配对(二分图)
[SDOI2016 Round1] 数字配对 ★★★ 输入文件:menci_pair.in 输出文件:menci_pair.out 简单对比 时间限制:1 s 内存限制:128 MB [题目描述] 有 ...
- cogs 2221. [SDOI2016 Round1] 数字配对
★★ 输入文件:pair.in 输出文件:pair.out 简单对比 时间限制:1 s 内存限制:128 MB [题目描述] 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两 ...
- 「SDOI2016」数字配对
「SDOI2016」数字配对 题目大意 传送门 题解 \(a_i\) 是 \(a_j\) 的倍数,且 \(\frac{a_i}{a_j}\) 是一个质数,则将 \(a_i,a_j\) 质因数分解后,其 ...
- 【BZOJ4514】【SDOI2016】数字配对 [费用流]
数字配对 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description 有 n 种数字,第 i 种数字是 ...
- [SDOI2016][bzoj4514] 数字配对 [费用流]
题面 传送门 思路 一个数字能且只能匹配一次 这引导我们思考:一次代表什么?代表用到一定上限(b数组)就不能再用,同时每用一次会产生价值(c数组) 上限?价值?网络流! 把一次匹配设为一点流量,那产生 ...
- 【LOJ】#2031. 「SDOI2016」数字配对
题解 这个图是个二分图,因为如果有一个奇环的话,我们会发现一个数变成另一个数要乘上个数不同的质数,显然不可能 然后我们发现这个不是求最大流,而是问一定价值的情况下最大流是多少,二分一个流量,加上一条边 ...
- loj2031 「SDOI2016」数字配对
跑最大费用最大流,注意到每次 spfa 出来的 cost 一定是越来越少的,啥时小于 \(0\) 了就停了吧. #include <iostream> #include <cstri ...
- 图论(费用流):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 是一个质数 ...
随机推荐
- bug--注意Android编译打包--找不到某某类
http://blog.csdn.net/mad1989/article/details/9142557 看到这篇 才解决问题= = 15,ClassNotFoundException: Didn't ...
- 个人作业4——alpha阶段个人总结(201521123003 董美凤)
一.个人总结 在alpha 结束之后, 每位同学写一篇个人博客, 总结自己的alpha 过程: 请用自我评价表:http://www.cnblogs.com/xinz/p/3852177.html 有 ...
- jquery 取消全选和全选功能 不全选
代码如下 function ckSelectAll() { if ($('#ckSelectAll').is(':checked') == true) { $("INPUT[name='ch ...
- Cannot open the disk 'D:\win7-ie8\Windows 7 x64.vmdk' or one of the snapshot
使用机子过程中断电,开机后使用虚拟机提示[Cannot open the disk 'D:\win7-ie8\Windows 7 x64.vmdk' or one of the snapshot],找 ...
- vSphere下安装Hyper-V
在vSphere 5.5中默认是无法嵌套安装Hyper-V的,必须在vSphere中稍作修改. 1. 勾选这两个选项,如果是灰色,请升级虚拟机版本至最新: 2. 在配置文件中手动加入这一行参数: 3. ...
- [转帖]超能课堂 CPU制作过程
http://www.expreview.com/50814.html 一般来说,我们对IC芯片的了解仅限于它概念,但是对于已经应用到各式各样的数码产品中IC芯片是怎么来的?大家可能只知道制作IC芯片 ...
- P2234 [HNOI2002]营业额统计
题目描述 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是 ...
- 【刷题】BZOJ 4636 蒟蒻的数列
Description 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个数列,初始值均为0,他进行N次操作,每次将数列[a,b)这个区间中所有比k小的数改为k,他想 ...
- 【刷题】BZOJ 1934 [Shoi2007]Vote 善意的投票
Description 幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉.对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神.虽然每个人都有自己的主见,但是为了照顾一下自己朋友的想法,他们也可 ...
- 【转】64位Ubuntu 16.04搭建嵌入式交叉编译环境arm-linux-gcc过程图解
64位Ubuntu 16.04搭建嵌入式交叉编译环境arm-linux-gcc过程图解,开发裸机环境之前需要先搭建其开发环境,毕竟工欲善其事必先利其器嘛. 安装步骤 1.准备工具安装目录 下载 ar ...