[CF 724E]Goods transportation
Posted alan_cty
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF 724E]Goods transportation相关的知识,希望对你有一定的参考价值。
Description
给出n个点,第i个点原来有p[i]个“good”(我也不知道为什么要叫这个名字,看来是Chinese round吧),可以售出s[i]个“good”。对于两个点i,j(i < j),你可以一次从i最多运送j个“good”到j,注意每对点只能运一次,求最多售出多少个“good”。
n<=10^4
Solution
这道题不是显然的最大流嘛~~
从源点向每个点连p[i],从每个点向汇点连s[i],然后每个点向后面的所有点连c,最大流就是答案。。。
但是,图的规模太大了,无法兹瓷,也不能动态开点TAT
肿么办呢?
我们注意到,最大流等于最小割!
然后这种图的最小割是可以用dp来求出来的!
设F[i][j]表示前i个点,有j个在S集里的最小割。
然后,我们把建模稍微改一下,先把能流的都流走,也就是源点向每个p[i] > s[i]的点连p[i]-s[i],每个p[i] < s[i]的点向汇点流s[i]-p[i]。
那么转移方程就显然了,判断一个点是在哪个集合中,自己手(kan)推(biao)一下就好了
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int N=1e4+5;
const ll inf=1e14;
ll f[2][N],p[N],s[N],ans,Min;
int n,c;
int main()
scanf("%d%d",&n,&c);
fo(i,1,n) scanf("%I64d",&p[i]);
fo(i,1,n) scanf("%I64d",&s[i]);
fo(i,1,n)
ans+=min(s[i],p[i]);int x=i%2,y=1-i%2;
fo(j,0,i)
f[x][j]=inf;
if (p[i]>s[i])
if (j!=i) f[x][j]=min(f[x][j],f[y][j]+p[i]-s[i]+(ll)j*c);
if (j) f[x][j]=min(f[x][j],f[y][j-1]);
else
if (j!=i) f[x][j]=min(f[x][j],f[y][j]+(ll)j*c);
if (j) f[x][j]=min(f[x][j],f[y][j-1]+s[i]-p[i]);
Min=f[n%2][0];
fo(i,1,n) Min=min(Min,f[n%2][i]);
printf("%I64d\\n",Min+ans);
以上是关于[CF 724E]Goods transportation的主要内容,如果未能解决你的问题,请参考以下文章
codeforces724E Goods transportation(欧拉回路)