●洛谷 1251 餐巾计划问题
●题链:
https://www.luogu.org/problemnew/show/1251
●题解:
一点启示:建图时要考虑到流量问题,即为了方便使用最小费用最大流算法,要把流量最大时为最终目的考虑进建图。
拆点,每天拆为两个点i, i',表示每天开始和每天结束
(s,i,ai,P):在第i天最多买ri个餐巾,花费为P;
(i,t,ai,0):第i天要用ai块餐巾;
(s,i',ai,0):第i天用剩的ai块旧餐巾;
(i',i+M,INF,F):第i天的旧餐巾送到快洗部,花费为F;
(i',i+N,INF,S):第i天的旧餐巾送到慢洗部,花费为S;
(i,i+1,INF,0):第i天的没用的餐巾可以留到第i+1天去用。
SPFA费用流:
#include<queue> #include<cstdio> #include<cstring> #include<iostream> #define MAXN 2050 #define INF 0x3f3f3f3f using namespace std; struct Edge{ int to[MAXN*12],cap[MAXN*12],cot[MAXN*12],nxt[MAXN*12],head[MAXN*2],ent; void Init(){ ent=2; memset(head,0,sizeof(head)); } void Adde(int u,int v,int w,int c){ to[ent]=v; cap[ent]=w; cot[ent]=c; nxt[ent]=head[u]; head[u]=ent++; to[ent]=u; cap[ent]=0; cot[ent]=-c; nxt[ent]=head[v]; head[v]=ent++; } int Next(int i,bool type){ return type?head[i]:nxt[i]; } }E; int a[MAXN]; int Day,P,M,F,N,S,SS,TT; int idx(int i,int k){ return i+Day*k; } bool spfa(long long &cost){ static bool inq[MAXN*2]; static int dis[MAXN*2],p[MAXN*2],flow[MAXN*2]; memset(dis,0x3f,sizeof(dis)); queue<int>q; q.push(SS); inq[SS]=1; dis[SS]=0; flow[SS]=INF; while(!q.empty()){ int u=q.front(); q.pop(); inq[u]=0; for(int i=E.Next(u,1);i;i=E.Next(i,0)){ int v=E.to[i]; if(!E.cap[i]||dis[v]<=dis[u]+E.cot[i]) continue; dis[v]=dis[u]+E.cot[i]; p[v]=i; flow[v]=min(flow[u],E.cap[i]); if(!inq[v]) inq[v]=1,q.push(v); } } if(dis[TT]==INF) return 0; int u=TT; cost+=1ll*flow[TT]*dis[TT]; while(u!=SS){ E.cap[p[u]]-=flow[TT]; E.cap[p[u]^1]+=flow[TT]; u=E.to[p[u]^1]; } return 1; } long long Mincost_Maxflow(){ long long cost=0; while(spfa(cost)); return cost; } int main() { E.Init(); scanf("%d",&Day); SS=2*Day+1; TT=2*Day+2; for(int i=1;i<=Day;i++){ scanf("%d",&a[i]); E.Adde(SS,idx(i,1),a[i],0); E.Adde(idx(i,0),TT,a[i],0); } scanf("%d%d%d%d%d",&P,&M,&F,&N,&S); for(int i=1,_i;i<=Day;i++){ E.Adde(SS,idx(i,0),a[i],P); _i=i+M; if(_i<=Day) E.Adde(idx(i,1),idx(_i,0),INF,F); _i=i+N; if(_i<=Day) E.Adde(idx(i,1),idx(_i,0),INF,S); } for(int i=1;i<=Day;i++){ if(i!=Day) E.Adde(idx(i,0),idx(i+1,0),INF,0); } long long ans=Mincost_Maxflow(); printf("%lld",ans); return 0; }
ZKW(dinic实现)费用流:
#include<queue> #include<cstdio> #include<cstring> #include<iostream> #define MAXN 2050 #define INF 0x3f3f3f3f using namespace std; struct Edge{ int to[MAXN*12],cap[MAXN*12],cot[MAXN*12],nxt[MAXN*12],head[MAXN*2],ent; void Init(){ ent=2; memset(head,0,sizeof(head)); } void Adde(int u,int v,int w,int c){ to[ent]=v; cap[ent]=w; cot[ent]=c; nxt[ent]=head[u]; head[u]=ent++; to[ent]=u; cap[ent]=0; cot[ent]=-c; nxt[ent]=head[v]; head[v]=ent++; } int Next(int i,bool type){ return type?head[i]:nxt[i]; } }E; int a[MAXN],cur[MAXN*2],dis[MAXN*2]; int Day,P,M,F,N,S,SS,TT; int idx(int i,int k){ return i+Day*k; } bool spfa(){ static bool inq[MAXN*2]; memset(dis,0x3f,sizeof(dis)); queue<int>q; q.push(TT); inq[TT]=1; dis[TT]=0; while(!q.empty()){ int u=q.front(); q.pop(); inq[u]=0; for(int i=E.Next(u,1);i;i=E.Next(i,0)){ int v=E.to[i]; if(!E.cap[i^1]||dis[v]<=dis[u]+E.cot[i^1]) continue; dis[v]=dis[u]+E.cot[i^1]; if(!inq[v]) inq[v]=1,q.push(v); } } return dis[SS]<INF; } int dfs(int u,int reflow){ if(u==TT||reflow==0) return reflow; int flowout=0,f,d=dis[u]; dis[u]=INF; for(int &i=cur[u];i;i=E.Next(i,0)){ int v=E.to[i]; if(d!=dis[v]+E.cot[i]||!E.cap[i]) continue; f=dfs(v,min(reflow,E.cap[i])); flowout+=f; E.cap[i^1]+=f; reflow-=f; E.cap[i]-=f; if(!reflow) break; } return flowout; } long long ZKW_Mincost(){ long long cost=0; while(spfa()){ memcpy(cur,E.head,sizeof(E.head)); cost+=1ll*dis[SS]*dfs(SS,INF); } return cost; } int main() { E.Init(); scanf("%d",&Day); SS=2*Day+1; TT=2*Day+2; for(int i=1;i<=Day;i++){ scanf("%d",&a[i]); E.Adde(SS,idx(i,1),a[i],0); E.Adde(idx(i,0),TT,a[i],0); } scanf("%d%d%d%d%d",&P,&M,&F,&N,&S); for(int i=1,_i;i<=Day;i++){ E.Adde(SS,idx(i,0),a[i],P); _i=i+M; if(_i<=Day) E.Adde(idx(i,1),idx(_i,0),INF,F); _i=i+N; if(_i<=Day) E.Adde(idx(i,1),idx(_i,0),INF,S); } for(int i=1;i<=Day;i++){ if(i!=Day) E.Adde(idx(i,0),idx(i+1,0),INF,0); } long long ans=ZKW_Mincost(); printf("%lld",ans); return 0; }
Do not go gentle into that good night.
Rage, rage against the dying of the light.
————Dylan Thomas