[ARC125E] Snack 题解
Leowang2009 · · 题解
题目传送门
思路
神仙网络流题。
将每种零食和每个小孩看成一个点,然后构造一个源点,连向每个零食,流量为每种零食的个数,然后再在零食与小孩之间连边,流量为小孩每种能吃的最大个数。最后构造一个汇点,每个小孩向汇点连边,流量为每个小孩最多可以吃的零食数。
建好图后,可以发现这是个最大流,但由于点数达到了
由最大流最小割定理可知,最大流等于最小割。恰好,在此题中,最小割较好处理。具体实现方法可以先将
如何选取切断的
代码实现
复杂度分析
时间复杂度瓶颈在排序(显然可以用快排),总体时间复杂度线性对数。
AC Code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
int n,m,a[N],b[N],c[N],s,ans=0x3f3f3f3f3f3f3f3f;
struct node{
int b,c;
}q[N];
bool cmp(node a,node b){
return a.c*b.b>b.c*a.b;//将除法改为乘法,精度更高,且速度更快
}//比较函数
signed main(){
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int i=1;i<=m;i++) scanf("%lld",&q[i].b);
for(int i=1;i<=m;i++) scanf("%lld",&q[i].c);//输入
sort(a+1,a+n+1);//将 A 从小到大排序
sort(q+1,q+m+1,cmp);//将小孩按 C/B 排序
for(int i=2;i<=n;i++) a[i]+=a[i-1];//做 A 的前缀和
for(int i=1;i<=m;i++) b[i]=b[i-1]+q[i].b;//做 B 的前缀和
for(int i=m;i;i--) c[i]=c[i+1]+q[i].c;//做 C 的后缀和
for(int i=0,j=1;i<=n;i++){
int res=a[i];//割断 A 的代价
for(;q[j].b*(n-i)<q[j].c;j++);//移动 j 指针
res+=(n-i)*b[j-1]+c[j];//总代价
ans=min(res,ans);//记录最小值
}//计算最小割
printf("%lld",ans);//输出
return 0;
}
完结撒花!