P1251 餐巾计划问题 (费用流)
作者:互联网
方法:
重点在建图!!!将一天拆成晚上和早上;
1. 从源点向每一天晚上连一条流量为当天所用餐巾x,费用为0的边;
2. 每一天早上向汇点连一条流量为当天所用餐巾x,费用为0的边;
3. 从每一天晚上向第二天晚上连一条流量为INF,费用为0的边,表示每天晚上可以将脏餐巾留到第二天晚上;
4. 从每一天晚上向这一天+快洗所用天数t1的那一天早上连一条流量为INF,费用为快洗所用钱数的边,表示每天晚上可以送去快洗部,在地i+t1天早上收到餐巾 ;
5. 从每一天晚上向这一天+慢洗所用天数t2的那一天早上连一条流量为INF,费用为慢洗所用钱数的边,表示每天晚上可以送去慢洗部,在地i+t2天早上收到餐巾;
6. 从起点向每一天早上连一条流量为INF,费用为购买餐巾所用钱数的边,表示每天早上可以购买餐巾 。
Code:
1 #include <bits/stdc++.h> 2 #define LL long long 3 using namespace std; 4 5 const int maxn=2000; 6 const int INF=0x7fffffff; 7 int N; 8 int S,T; 9 struct Edge{ 10 int next, from, to, remain,fi; 11 }e[100000]; 12 int head[10000]; 13 int en; 14 LL dis[10000]; 15 int preEdge[10000]; 16 queue<int> q; 17 int inqueue[10000]; 18 LL res; 19 int minflow[10000]; 20 21 void addEdge(int from, int to, int flow, int fi){ 22 e[en].next=head[from]; 23 e[en].from=from; 24 e[en].to=to; 25 e[en].remain=flow; 26 e[en].fi=fi; 27 head[from]=en; 28 ++en; 29 } 30 31 void add(int from, int to, int flow, int fi){ 32 addEdge(from,to,flow,fi); 33 addEdge(to,from,0,-fi); 34 } 35 36 void spfa(){ 37 memset(minflow,0,sizeof(minflow)); 38 memset(dis,127,sizeof(dis)); 39 memset(preEdge,-1,sizeof(preEdge)); 40 dis[S]=0; 41 minflow[S]=INF; 42 q.push(S); 43 inqueue[S]=1; 44 while(!q.empty()){ 45 int u=q.front(); 46 q.pop(); 47 inqueue[u]=0; 48 for(int i=head[u];i!=-1;i=e[i].next){ 49 int v=e[i].to; 50 int c=e[i].fi; 51 if(e[i].remain>0 && dis[u]+c<dis[v]){ 52 dis[v]=dis[u]+c; 53 preEdge[v]=i; 54 minflow[v]=min(minflow[u],e[i].remain); 55 if(!inqueue[v]){ 56 q.push(v); 57 inqueue[v]=1; 58 } 59 } 60 } 61 } 62 } 63 64 void EK(){ 65 66 while(true){ 67 spfa(); 68 if(preEdge[T]==-1) break; 69 int v=T; 70 while(true){ 71 int edge=preEdge[v]; 72 if(edge==-1) break; 73 e[edge].remain-=minflow[T]; 74 e[edge^1].remain+=minflow[T]; 75 v=e[edge].from; 76 } 77 res+=dis[T]*minflow[T]; 78 } 79 } 80 81 int main(){ 82 memset(head,-1,sizeof(head)); 83 scanf("%d", &N); 84 S=0; 85 T=2*N+1; 86 for(int i=1;i<=N;++i){ 87 int c; 88 scanf("%d", &c); 89 add(i,T,c,0); 90 add(S,i+N,c,0); 91 } 92 int p, m, f, n, s; 93 scanf("%d %d %d %d %d", &p, &m, &f, &n, &s); 94 for(int i=1;i<=N;++i){ 95 add(S,i,INF,p); 96 if(i+1<=N){ 97 add(i+N,i+1+N,INF,0); 98 } 99 if(i+m<=N){ 100 add(i+N,i+m,INF,f); 101 } 102 if(i+n<=N){ 103 add(i+N,i+n,INF,s); 104 } 105 } 106 EK(); 107 printf("%lld",res); 108 return 0; 109 }
标签:费用,en,P1251,int,餐巾,fi,INF,dis 来源: https://www.cnblogs.com/FEIIEF/p/12244588.html