[網路流24題-13]餐巾計劃問題
阿新 • • 發佈:2018-12-10
餐巾計劃問題
寫網路流寫的頭昏腦漲QAQ大概還是太菜了
比較有趣的建圖題
對於每一個點拆點拆成早晨和晚上分別為 i 和 i'
1. s -> i (r,p) 每天早晨可以買最多r條新餐巾 一條p分
2. s -> i' (r,0) 每天用剩下r條髒餐巾 沒有代價
3. i -> t (r,0) 每天要用r條幹淨餐巾 沒有代價
4. i' -> i+m (inf,f) 髒毛巾送到快洗店 洗乾淨送回來是第i+m天 每條花費代價f分
5. i' -> i+n (inf,s) 髒毛巾送到慢洗店 洗乾淨送回來是第i+n天 每條花費代價s分
6. i' -> (i+1)' (inf,s) 每條髒毛巾留到第二天再處理 沒有代價
神建圖題QAQ 天真的我以為n^2的圖也可以跑的QAQ 難受的一批
果然腦子題還是不適合我
附程式碼。
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #define inf 2002122500 #define mxn 2010 #define ll long long using namespace std; struct edge{int to,lt,fr;ll f,c;}e[mxn*40]; queue<int> que;int in[mxn*4];bool vis[mxn*4]; int cnt=1,nn,s,t,from[mxn*4];ll dis[mxn*4]; void add(int x,int y,ll f,ll c) { e[++cnt].to=y;e[cnt].lt=in[x];e[cnt].fr=x; e[cnt].f=f;e[cnt].c=c;in[x]=cnt; e[++cnt].to=x;e[cnt].lt=in[y];e[cnt].fr=y; e[cnt].f=0;e[cnt].c=-c;in[y]=cnt; } bool spfa() { for(int i=1;i<=nn;i++) dis[i]=inf,vis[i]=0; dis[s]=0;vis[s]=1;que.push(s); while(!que.empty()) { int x=que.front();que.pop(); for(int i=in[x];i;i=e[i].lt) { int y=e[i].to; if(dis[y]>dis[x]+e[i].c&&e[i].f) { dis[y]=dis[x]+e[i].c;from[y]=i; if(!vis[y]) que.push(y),vis[y]=1; } } vis[x]=0; } return dis[t]<inf; } ll cost() { ll flow=inf; for(int i=t;i!=s;i=e[from[i]].fr) flow=min(flow,e[from[i]].f); for(int i=t;i!=s;i=e[from[i]].fr) e[from[i]].f-=flow,e[from[i]^1].f+=flow; return dis[t]*flow; } ll flow() { ll ans=0; while(spfa()) ans+=cost(); //printf("%d\n",dis[t]); return ans; } int r[mxn]; int main() { int n,m,f,p,ss,N; scanf("%d",&N);s=N*2+1;t=s+1;nn=t; for(int i=1;i<=N;i++) { scanf("%d",&r[i]); add(i,t,r[i],0); add(s,i+N,r[i],0); } scanf("%d%d%d%d%d",&p,&m,&f,&n,&ss); for(int i=1;i<=N;i++) { add(s,i,r[i],p); if(i+m<=N) add(i+N,i+m,inf,f); if(i+n<=N) add(i+N,i+n,inf,ss); if(i<=N) add(i+N,i+N+1,inf,0); } printf("%lld\n",flow()); return 0; }