zoukankan      html  css  js  c++  java
  • 【Luogu】P1251餐巾计划(上下界费用流)

      题目链接

      学了一下上下界费用流,似乎很nb。但是我说得不好,所以这里给出博客链接。

      某dalao的博客

      然后这道题的解法就是先用上下界费用流的建图方式连早上和晚上之间的那条边,保证当天一定会有r条或以上的餐巾可用。

      然后考虑买,快洗,慢洗和放起来的诸多情况。

      

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cctype>
    #include<queue>
    #define maxn 5030
    using namespace std;
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    struct Edge{
        int from,next,to,val,dis;
    }edge[maxn*20];
    int head[maxn],num;
    inline void addedge(int from,int to,int val,int dis){
        edge[++num]=(Edge){from,head[from],to,val,dis};
        head[from]=num;
    }
    inline void add(int from,int to,int val,int dis){
        addedge(from,to,val,dis);
        addedge(to,from,0,-dis);
    }
    
    inline int count(int i){    return i&1?i+1:i-1;    }
    
    int dis[maxn];
    int pre[maxn];
    bool vis[maxn];
    int flow[maxn];
    int Start,End;
    
    int spfa(){
        memset(dis,127/3,sizeof(dis));    int pinf=dis[0];
        dis[Start]=0;    flow[Start]=0x7fffffff;
        queue<int>q; q.push(Start);
        while(!q.empty()){
            int from=q.front();    q.pop();    vis[from]=0;
            for(int i=head[from];i;i=edge[i].next){
                int to=edge[i].to;
                if(edge[i].val==0||dis[to]<=dis[from]+edge[i].dis)    continue;
                dis[to]=dis[from]+edge[i].dis;
                pre[to]=i;    flow[to]=min(flow[from],edge[i].val);
                if(vis[to])    continue;
                vis[to]=1;    q.push(to);
            }
        }
        if(dis[End]==pinf)    return 0;
        int now=End;
        while(now!=Start){
            int ret=pre[now];
            edge[ret].val-=flow[End];    edge[count(ret)].val+=flow[End];
            now=edge[ret].from;
        }
        return (long long)dis[End]*flow[End];
    }
    
    int r[maxn];
    
    int main(){
        int N=read();    End=N*2+1;
        for(int i=1;i<=N;++i){
            r[i]=read();
            add(Start,i+N,r[i],0);
            add(i,End,r[i],0);
            add(i,i+N,0x7fffffff,0);
        }
        int p=read(),m=read(),f=read(),n=read(),s=read();
        for(int i=1;i<=N;++i){
            add(Start,i,0x7fffffff,p);
            if(i!=N)    add(i,i+1,0x7fffffff,0);
            if(i+m>N)    continue;
            add(i+N,i+m,0x7fffffff,f);
            if(i+n>N)    continue;
            add(i+N,i+n,0x7fffffff,s);
            
        }
        long long ans=0;
        while(1){
            long long now=spfa();
            if(now==0)    break;
            ans+=now;
        }
        printf("%lld
    ",ans);
        return 0;
    }

    https://www.luogu.org/problemnew/show/P1251

  • 相关阅读:
    洛谷 P1194 飞扬的小鸟 题解
    洛谷 P1197 星球大战 题解
    洛谷 P1879 玉米田Corn Fields 题解
    洛谷 P2796 Facer的程序 题解
    洛谷 P2398 GCD SUM 题解
    洛谷 P2051 中国象棋 题解
    洛谷 P1472 奶牛家谱 Cow Pedigrees 题解
    洛谷 P1004 方格取数 题解
    洛谷 P2331 最大子矩阵 题解
    洛谷 P1073 最优贸易 题解
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8448905.html
Copyright © 2011-2022 走看看