Codeforces 724 E Goods transportation

Description

有 (n) 个点,每个点有一个入流和出流,每个点与编号比它大的点连边,容量为 (c) ,求最大流.

Sol

DP.

这种特殊的图可以DP,把最大流转化成最小割.

最小割就是 (sum s_i,iin S + sum p_j,j in T + c sum [i in S][jin T]) .

最后一个式子其实就是 (S) 与 (T) 的割边.

(f[i][j]) 表示前 (i) 个点有 (j) 个点 (in S)

转移就是对于一个点加入 (S) 还是加入 (T) 取 (min)

(f[i][j]=min{f[i][j-1]+s[i],f[i][j]+j*c+p[i]})

倒序枚举即可 复杂度 (O(frac {n(n-1)} {2}))

Code

#include<cstdio>
#include<iostream>
using namespace std;

typedef long long LL;
const int N = 10005;
const LL INF = 1LL<<60;

int n,c;LL ans;
int p[N],s[N];
LL f[N];

inline int in(int x=0,char ch=getchar()){ while(ch>'9'||ch<'0') ch=getchar();
	while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; }
int main(){
	n=in(),c=in();
	for(int i=1;i<=n;i++) p[i]=in();
	for(int i=1;i<=n;i++) s[i]=in();
	for(int i=1;i<=n;i++) f[i]=INF;
	
	for(int i=1;i<=n;i++){
		for(int j=i;j;j--)
			f[j]=min(f[j-1]+s[i],f[j]+(LL)j*c+p[i]);
		f[0]+=p[i];
	}
	ans=INF;
	
//	for(int i=0;i<=n;i++) cout<<f[i]<<" ";cout<<endl;
	
	for(int i=0;i<=n;i++) ans=min(ans,f[i]);
	return cout<<ans<<endl,0;
}

  

原文地址:https://www.cnblogs.com/beiyuoi/p/5957574.html