• 洛谷 P1251 餐巾计划问题


    题目链接

    最小费用最大流。

    每天拆成两个点,早上和晚上;

    晚上可以获得(r_i)条脏毛巾,从源点连一条容量为(r_i),费用为0的边。

    早上要供应(r_i)条毛巾,连向汇点一条容量为(r_i)吗,费用为0的边。

    每天可以买毛巾,晚上向第二天早上连一条费用为(p),容量为(inf)的边。

    可以送快洗,晚上向(m)天之后的早上连费用(f),容量(inf)的边

    可以送慢洗,晚上向(n)天之后的早上连费用(s),容量(inf)的边

    脏毛巾可以留到第二天晚上,源点向第二天晚上连一条容量(r_i),费用0的边。

    最后跑费用流即可。

    常数巨大的代码

    #include<bits/stdc++.h>
    using namespace std;
     
    #define int long long 
     
    inline void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+(ch^48);x*=f;
    }
     
    inline void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar((x%10)^48);
    }
    inline void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
     
    #define maxn 1000050
    
    int n,m,s,t,max_flow,tot=1,min_cost;
    int head[maxn],dis[maxn],vis[maxn],v[70][70];
    struct edge{int to,nxt,w,c;}e[maxn<<1];
    
    void add(int u,int v,int w,int c) {e[++tot]=(edge){v,head[u],w,c},head[u]=tot;}
    void ins(int u,int v,int w,int c) {add(u,v,w,c),add(v,u,0,-c);}
    
    int spfa() {
        memset(vis,0,sizeof vis);
        memset(dis,63,sizeof dis);
        queue<int > q;q.push(s);dis[s]=0;vis[s]=1;
        while(!q.empty()) {
            int now=q.front();q.pop();vis[now]=0;
            for(int i=head[now];i;i=e[i].nxt)
                if(e[i].w>0&&dis[e[i].to]>dis[now]+e[i].c) {
                    dis[e[i].to]=dis[now]+e[i].c;
                    if(!vis[e[i].to]) vis[e[i].to]=1,q.push(e[i].to);
                }
        }return dis[t]<1e9;
    }
    
    int dfs(int u,int f) {
        if(u==t) {max_flow+=f,min_cost+=f*dis[t],vis[t]=1;return f;}
        vis[u]=1;int used=0;
        for(int i=head[u];i;i=e[i].nxt)
            if(e[i].w>0&&dis[e[i].to]==dis[u]+e[i].c&&!vis[e[i].to]) {
                int flow=dfs(e[i].to,min(f-used,e[i].w));
                if(flow>0) {e[i].w-=flow,e[i^1].w+=flow;return flow;}
                if(used==f) break;
            }
        return used;
    }
    
    void cost_flow() {
        while(spfa()) {
            vis[t]=1;
            while(vis[t]) memset(vis,0,sizeof vis),dfs(s,1e9);
        }
    }
    
    signed main() {
        read(n);int x;s=0,t=n*2+1;
        for(int i=1;i<=n;i++) read(x),ins(s,i,x,0),ins(i+n,t,x,0);
        int p,m,f,nn,ss;read(p),read(m),read(f),read(nn),read(ss);
        for(int i=1;i<=n;i++) {
            ins(s,i+n,1e7,p);
            if(i+m<=n) ins(i,i+m+n,1e7,f);
            if(i+nn<=n) ins(i,i+nn+n,1e7,ss);
            if(i+1<=n) ins(i,i+1,1e7,0);
        }cost_flow();write(min_cost);
        return 0;
    }
    
    
  • 相关阅读:
    Robotium--通过Id寻找控件
    Robotium--scroll操作系列
    Robotium--takeScreenshot(截图)
    Android AIDL[Android Interface Definition Language]跨进程通信
    Android 8.0以上版本加载walkspace
    MTK Android [输入法]客制化系统默认输入法-搜狗输入法
    MTK Android 计算器Calculator输入暗码!77!+,启动工厂测试apk
    Android AndroidManifest.xml详解
    MTK Android 设置下添加一级菜单[ZedielPcbTest]
    Linux教程
  • 原文地址:https://www.cnblogs.com/hbyer/p/9921812.html
Copyright © 2020-2023  润新知