【网络流24题】餐巾计划问题

标签:费用流

Solution

由于每天餐厅需要 \(r_i\) 份餐巾,产生 \(r_i\) 份需清洗餐巾,考虑将每天拆成两个点 \(X_i\)\(Y_i\) ,其中 \(X_i\) 需要向汇点 \(T\) 汇入 \(r_i\) 份餐巾,\(Y_i\)\(X_j\) 汇入清洗过的餐巾。

从源点 \(S\)\(X_i\) 连一条容量无限,单位费用为 \(p\) 的边,表示购买餐巾;向 \(Y_i\) 连一条容量为 \(r_i\),单位费用为 \(0\) 的边,表示该天用过的餐巾。

此外,\(Y_i\)\(Y_{i+1}\) 连一条容量无限,单位费用为 \(0\) 的边,表示延期清洗餐巾;分别向 \(X_{i+m}\)\(X_{i+n}\) 连容量无限,单位费用分别为 \(f\)\(p\) 的边,表示快洗与慢洗餐巾。

最后跑一边最小费用最大流即可。

Code

#include<bits/stdc++.h>
#define M 4005
using namespace std;
typedef long long ll;
typedef double db;
char IO;
int rd(){
	int num=0;bool f=0;
	while(IO=getchar(),IO<48||IO>57)if(IO=='-')f=1;
	do num=(num<<1)+(num<<3)+(IO^48);
	while(IO=getchar(),IO>=48&&IO<=57);
	return f?-num:num;
}
bool f2;
int n,m,S,T;
int to[M*12],nxt[M*12],hd[M],cnte=1;
ll val[M*12],cost[M*12];
void Adde(int u,int v,ll w,ll c){
	to[++cnte]=v;val[cnte]=w;cost[cnte]=c;
	nxt[cnte]=hd[u];hd[u]=cnte;
}
void Add(int u,int v,ll w,ll c){
	Adde(u,v,w,c);Adde(v,u,0,-c);
}
ll dep[M];
int cur[M];
bool vis[M];
queue<int> Q;
bool SPFA(){
	memset(dep,63,sizeof(dep));
	memcpy(cur,hd,sizeof(cur));
	dep[S]=1;Q.push(S);
	int u,v;
	while(!Q.empty()){
		u=Q.front();Q.pop();
		vis[u]=0;
		for(int i=hd[u];i;i=nxt[i]){
			v=to[i];
			if(val[i]&&dep[u]+cost[i]<dep[v]){
				dep[v]=dep[u]+cost[i];
				if(!vis[v])Q.push(v),vis[v]=1;
			}
		}
	}
	return dep[T]!=0x3f3f3f3f3f3f3f3f;
}
ll micost;
ll DFS(int u,ll flow){
	if(u==T)return flow;
	vis[u]=1;
	ll res=0,f;
	for(int i=cur[u],v;i;i=nxt[i]){
		cur[u]=i;v=to[i];
		if(vis[v]||dep[v]!=dep[u]+cost[i])continue;
		if(val[i]&&(f=DFS(v,min(flow,val[i])))>0){
			val[i]-=f;val[i^1]+=f;
			res+=f;flow-=f;
			micost+=f*cost[i];
		}
	}
	vis[u]=0;
	return res;
}
ll C[M];
bool f1;
int main(){
//	cout<<1.0*(&f1-&f2)/1024.0/1024.0<<endl;
	n=rd();S=0,T=2*n+1;
	for(int i=1;i<=n;++i)
		C[i]=rd();
	ll p=rd(),a=rd(),f=rd(),b=rd(),s=rd();
	for(int i=1;i<=n;++i){
		Add(S,i,1e18,p);
		Add(i,T,C[i],0);
		Add(S,n+i,C[i],0);
		if(i+a<=n)Add(n+i,i+a,1e18,f);
		if(i+b<=n)Add(n+i,i+b,1e18,s);
		if(i!=n)Add(n+i,n+i+1,1e18,0);
	}
	while(SPFA())DFS(S,1e18);
	cout<<micost;
	return 0;
}
posted @ 2021-07-15 19:37  Alnorie  阅读(46)  评论(0)    收藏  举报