首页 > 其他 > 详细

洛谷P1251 餐巾计划问题

时间:2018-07-16 00:08:25      阅读:163      评论:0      收藏:0      [点我收藏+]

题目链接:https://www.luogu.org/problemnew/show/P1251

知识点:  最小费用最大流

建图思路:

  用两个点代表一天,从源点向一天中的第一个点连一条边,容量为 \(INF\),费用为 \(p\),再从这个点向汇点连一条边,容量为 \(r_i\),费用为 \(0\),这个点保证了每一天获得的餐巾量为 \(r_i\)。再从源点向第二个点连一条边,容量 \(r_i\),费用为 \(0\),这个点用来处理用过的餐巾,从这一点往 \(m\) 天后的第一个点连一条边,容量为 \(INF\),费用为 \(f\),代表送去快洗,\(m\)天后才取回;同理再从第二个点往 \(n\) 天后的第一个点连一条边,容量为 \(INF\),费用为 \(s\),代表送去慢洗;最后从这一天的第二个点往下一天的第二个点连一条边,容量为 \(INF\),费用为 \(0\),代表把用过的餐巾保存起来延期送洗。

AC代码:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef long long LL;
  4 const int MAXN=5000;
  5 const int MAXM=30000;
  6 const LL INF=1e18;
  7 struct Edge{
  8     int to,Next;
  9     LL cap,flow,cost;
 10 }edge[MAXM];
 11 int head[MAXN],tol;
 12 int pre[MAXN];
 13 LL dis[MAXN];
 14 bool vis[MAXN];
 15 int N;
 16 void init(int n){
 17     N=n;
 18     tol=0;
 19     memset(head,-1,sizeof(head));
 20 }
 21 void addedge(int u,int v,LL cap,LL cost){
 22     edge[tol].to=v;
 23     edge[tol].cap=cap;
 24     edge[tol].cost=cost;
 25     edge[tol].flow=0;
 26     edge[tol].Next=head[u];
 27     head[u]=tol++;
 28     edge[tol].to=u;
 29     edge[tol].cap=0;
 30     edge[tol].cost=-cost;
 31     edge[tol].flow=0;
 32     edge[tol].Next=head[v];
 33     head[v]=tol++;
 34 }
 35 bool spfa(int s,int t){
 36     queue<int> q;
 37     for(int i=0;i<N;i++){
 38         dis[i]=INF;
 39         vis[i]=false;
 40         pre[i]=-1;
 41     }
 42     dis[s]=0;
 43     vis[s]=true;
 44     q.push(s);
 45     while(!q.empty()){
 46         int u=q.front();
 47         q.pop();
 48         vis[u]=false;
 49         for(int i=head[u];i!=-1;i=edge[i].Next){
 50             int v=edge[i].to;
 51             if(edge[i].cap>edge[i].flow &&
 52                dis[v]>dis[u]+edge[i].cost){
 53                 dis[v]=dis[u]+edge[i].cost;
 54                 pre[v]=i;
 55                 if(!vis[v]){
 56                     vis[v]=true;
 57                     q.push(v);
 58                 }
 59             }
 60         }
 61     }
 62     if(pre[t]==-1)  return false;
 63     else    return true;
 64 }
 65 LL minCostMaxflow(int s,int t,LL &cost){
 66     LL flow=0;
 67     cost=0;
 68     while(spfa(s,t)){
 69         LL Min=INF;
 70         for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){
 71             if(Min>edge[i].cap-edge[i].flow)
 72                 Min=edge[i].cap-edge[i].flow;
 73         }
 74         for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){
 75             edge[i].flow+=Min;
 76             edge[i^1].flow-=Min;
 77             cost+=edge[i].cost*Min;
 78         }
 79         flow+=Min;
 80     }
 81     return flow;
 82 }
 83 
 84 LL r[2000+5];
 85 int main(){
 86     int tN;
 87     scanf("%d",&tN);
 88     for(int i=1;i<=tN;i++)
 89         scanf("%lld",&r[i]);
 90     int m1,n1;
 91     LL p1,f1,s1;
 92     scanf("%lld%d%lld%d%lld",&p1,&m1,&f1,&n1,&s1);
 93     init(tN*2+2);
 94     int s=0,t=tN*2+1;
 95     
 96     for(int i=1;i<tN;i++){
 97         addedge(i+tN,i+1+tN,INF,0);
 98     }
 99     for(int i=1;i<=tN;i++){
100         addedge(s,i,INF,p1);
101         addedge(i,t,r[i],0);
102         addedge(s,i+tN,r[i],0);
103         if(i+m1<=tN)
104             addedge(i+tN,i+m1,INF,f1);
105         if(i+n1<=tN)
106             addedge(i+tN,i+n1,INF,s1);
107     }
108     LL ans;
109     minCostMaxflow(s,t,ans);
110     printf("%lld\n",ans);
111     return 0;
112 }

 

洛谷P1251 餐巾计划问题

原文:https://www.cnblogs.com/Blogggggg/p/9315655.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!