zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    0909初识操作系统
    实验四主存空间的分配和回收
    实验一 DOS命令解释程序的编写
    0909关于操作系统
    实验四主存空间的分配和回收
    实验3评价
    实验一 DOS命令解释程序的编写
    实验三、进程调度模拟程序实验
    实验二、作业调度实验
    0909 第一次上机课之《为什么学操作系统?》
  • 原文地址:https://www.cnblogs.com/FEIIEF/p/12244588.html
Copyright © 2011-2022 走看看