[codeforces724e]Goods transportation 解题报告

来源:互联网 发布:阿里云 域名解析到网址 编辑:程序博客网 时间:2024/05/01 03:26

这题好神呀。

首先这是一个网络流模型,考虑每个点都向编号比它大的点连一条容量为c的边,然后如果pisi,就从source向i连一条容量为pisi的边,否则就从i向sink连一条容量为sipi的边,这样的话最大流就是答案。
但是这个图太大了,不能直接跑最大流,也无法优化。
所以我们可以转而考虑最小割,我们发现如果我们知道了割中的点是哪些,其实是可以直接算出割的大小的。
所以如果设f(i,j)表示前i个点,S中有j个的最小割。那么

f(i,j)={min(f(i1,j)+pisi+jc,f(i1,j1)),pisimin(f(i1,j)+jc,f(i1,j1)+sipi),pi<si

代码:

#include<stdio.h>#include<iostream>using namespace std;#include<algorithm>const int N=1e4+5;int p[N],s[N];typedef long long LL;LL f[N];int main(){    //cout<<(sizeof(rest)>>20)<<endl;    //freopen("cf724e.in","r",stdin);    int n,c;    scanf("%d%d",&n,&c);    for(int i=1;i<=n;++i)scanf("%d",p+i);    for(int i=1;i<=n;++i)scanf("%d",s+i);    LL ans=0;    for(int i=1;i<=n;++i)    {        ans+=min(s[i],p[i]);        if(s[i]<=p[i])f[i]=f[i-1];        else f[i]=f[i-1]+s[i]-p[i];        for(int j=i-1;j>=0;--j)            if(s[i]<=p[i])            {                f[j]+=p[i]-s[i]+(LL)j*c;                if(j)f[j]=min(f[j],f[j-1]);            }            else{                f[j]+=(LL)j*c;                if(j)f[j]=min(f[j],f[j-1]+s[i]-p[i]);            }        //for(int j=0;j<=i;++j)printf("f(%d,%d)=%I64d\n",i,j,f[j]);    }    cout<<(ans+*min_element(f,f+n+1))<<endl;}

总结:
①。。感觉经常想不到网络流呢。什么样的题要用网络流呢?也许是方案非常复杂的那种吧,就像这道题。所以如果感觉方案很鬼畜难以统计就考虑一下网络流吧!
②注意最大流与最小割的转化。

0 0
原创粉丝点击