zoukankan      html  css  js  c++  java
  • 洛谷P1251 餐巾计划问题(费用流)

    传送门

    不得不说这题真是思路清奇,真是网络流的一道好题,完全没想到网络流的建图还可以这么建

    我们把每一个点拆成两个点,分别表示白天和晚上,白天可以得到干净的餐巾(购买的,慢洗的,快洗的),晚上可以得到脏餐巾(之前剩下的,今天用过的)

    1.每一天,我们都从源点向晚上连边,容量为餐巾,费用$0$,表示可以免费获得这么多餐巾,从早上想汇点连边,容量为餐巾,费用为$0$,表示可以免费提供这么多餐巾,流满时表示当天餐巾够用

    2.从每一天晚上向第二天晚上连边,容量$inf$,费用$0$,表示可以把脏餐巾留到第二天晚上(因为有可能有的餐巾不用洗第二天就已经够了)

    3.在每一天晚上向这一天的$t1$天之后的早上连容量为$inf$,费用快洗钱数的边,表示每天晚上可以快洗之后为$t1$天之后送去干净的餐巾

    4.在每一天晚上向这一天的$t2$天之后的早上连容量为$inf$,费用慢洗钱数的边,表示每天晚上可以慢洗之后为$t2$天之后送去干净的餐巾

    5.从起点向每一天早上连容量$inf$,费用为买餐巾费用的边,表示每天早上都可以买餐巾

    ps:后四点建边时要判断是否合法

    然后为了让每天早上餐巾都够用,得让网络流满,所以跑一个最小费用最大流即可

     1 //minamoto
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<queue>
     5 #include<cstring>
     6 #define inf 0x3f3f3f3f
     7 #define ll long long
     8 using namespace std;
     9 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    10 char buf[1<<21],*p1=buf,*p2=buf;
    11 inline int read(){
    12     #define num ch-'0'
    13     char ch;bool flag=0;int res;
    14     while(!isdigit(ch=getc()))
    15     (ch=='-')&&(flag=true);
    16     for(res=num;isdigit(ch=getc());res=res*10+num);
    17     (flag)&&(res=-res);
    18     #undef num
    19     return res;
    20 }
    21 const int N=4005,M=50005;
    22 int ver[M],Next[M],head[N],edge[M],flow[M],tot=1;
    23 int disf[N],vis[N],Pre[N],last[N];ll dis[N];
    24 int n,m,t1,t2,m1,m2,s,t;
    25 queue<int> q;
    26 inline void add(int u,int v,int f,int e){
    27     ver[++tot]=v,Next[tot]=head[u],head[u]=tot,flow[tot]=f,edge[tot]=e;
    28     ver[++tot]=u,Next[tot]=head[v],head[v]=tot,flow[tot]=0,edge[tot]=-e;
    29 }
    30 bool spfa(){
    31     memset(dis,0x3f,sizeof(dis));
    32     q.push(s),dis[s]=0,disf[s]=inf,Pre[t]=-1;
    33     while(!q.empty()){
    34         int u=q.front();q.pop();vis[u]=0;
    35         for(int i=head[u];i;i=Next[i]){
    36             int v=ver[i];
    37             if(flow[i]&&dis[v]>dis[u]+edge[i]){
    38                 dis[v]=dis[u]+edge[i],last[v]=i,Pre[v]=u;
    39                 disf[v]=min(disf[u],flow[i]);
    40                 if(!vis[v]) vis[v]=1,q.push(v);
    41             }
    42         }
    43     }
    44     return ~Pre[t];
    45 }
    46 ll dinic(){
    47     ll mincost=0;
    48     while(spfa()){
    49         int u=t;mincost+=disf[t]*dis[t];
    50         while(u!=s){
    51             flow[last[u]]-=disf[t];
    52             flow[last[u]^1]+=disf[t];
    53             u=Pre[u];
    54         }
    55     }
    56     return mincost;
    57 }
    58 int main(){
    59     n=read();
    60     s=0,t=2*n+1;
    61     for(int i=1;i<=n;++i){
    62         int x=read();
    63         add(s,i,x,0),add(i+n,t,x,0);
    64     }
    65     m=read(),t1=read(),m1=read(),t2=read(),m2=read();
    66     for(int i=1;i<=n;++i){
    67         if(i+1<=n) add(i,i+1,inf,0);
    68         if(i+t1<=n) add(i,i+n+t1,inf,m1);
    69         if(i+t2<=n) add(i,i+n+t2,inf,m2);
    70         add(s,i+n,inf,m);
    71     }
    72     printf("%lld
    ",dinic());
    73     return 0;
    74 }
  • 相关阅读:
    Codeforces Round #388 (Div. 2)
    Codeforces Round #388 (Div. 2)
    Codeforces Round #388 (Div. 2)
    FZU 1914 单调队列
    ACM学习历程—POJ 3764 The xor-longest Path(xor && 字典树 && 贪心)
    ACM学习历程—SGU 275 To xor or not to xor(xor高斯消元)
    ACM学习历程—CSU 1216 异或最大值(xor && 贪心 && 字典树)
    ACM学习历程—HDU 5512 Pagodas(数学)
    ACM学习历程—HDU5521 Meeting(图论)
    ACM学习历程—HDU1030 Delta-wave(数学)
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9507521.html
Copyright © 2011-2022 走看看