zoukankan      html  css  js  c++  java
  • BZOJ 1221 软件开发(费用流)

    容易看出这是显然的费用流模型。

    把每天需要的餐巾数作为限制。需要将天数拆点,x’表示每天需要的餐巾,x’’表示每天用完的餐巾。所以加边 (s,x',INF,0),(x'',t,INF,0).

    餐巾可以新买。所以需要加边(s,x'',INF,f)。

    没用完餐巾可以留到下一天,所以加边(x',x+1',INF,0).

    送往快洗店,加边(x',x+a+1'',INF,fa). 送往慢洗店,加边(x',x+b+1'',INF,fb).

    跑一遍费用流即可。由于该图是一种特殊的结构,类二分图结构。用ZKW费用流可以快速出解。

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi 3.1415926535
    # define eps 1e-9
    # define MOD 100000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=2005;
    //Code begin...
    
    struct Edge{
        int to, next, cap, flow, cost;
        Edge(int _to=0, int _next=0, int _cap=0, int _flow=0, int _cost=0):
        to(_to), next(_next), cap(_cap), flow(_flow), cost(_cost){}
    }edge[50005];
    struct ZKW_MinCostMaxFlow{
        int head[50005], tot, cur[50005], dis[50005], ss, tt, n, min_cost, max_flow;
        bool vis[50005];
        void init(){tot=0; mem(head,-1);}
        void addedge(int u, int v, int cap, int cost){
            edge[tot]=Edge(v,head[u],cap,0,cost);
            head[u]=tot++;
            edge[tot]=Edge(u,head[v],0,0,-cost);
            head[v]=tot++;
        }
        int aug(int u, int flow){
            if (u==tt) return flow;
            vis[u]=true;
            for (int i=cur[u]; i!=-1; i=edge[i].next) {
                int v=edge[i].to;
                if (edge[i].cap>edge[i].flow&&!vis[v]&&dis[u]==dis[v]+edge[i].cost) {
                    int tmp=aug(v,min(flow,edge[i].cap-edge[i].flow));
                    edge[i].flow+=tmp; edge[i^1].flow-=tmp; cur[u]=i;
                    if (tmp) return tmp;
                }
            }
            return 0;
        }
        bool modify_label(){
            int d=INF;
            FO(u,0,n) if (vis[u]) for (int i=head[u]; i!=-1; i=edge[i].next) {
                int v=edge[i].to;
                if (edge[i].cap>edge[i].flow&&!vis[v]) d=min(d,dis[v]+edge[i].cost-dis[u]);
            }
            if (d==INF) return false;
            FO(i,0,n) if (vis[i]) vis[i]=false, dis[i]+=d;
            return true;
        }
        PII mincostmaxflow(int start, int end, int nn){
            ss=start, tt=end, n=nn; min_cost=max_flow=0;
            FO(i,0,n) dis[i]=0;
            while (1) {
                FO(i,0,n) cur[i]=head[i];
                while (1) {
                    FO(i,0,n) vis[i]=false;
                    int tmp=aug(ss,INF);
                    if (tmp==0) break;
                    max_flow+=tmp; min_cost+=tmp*dis[ss];
                }
                if (!modify_label()) break;
            }
            return mp(min_cost,max_flow);
        }
    }solve;
    int val[N];
    int main ()
    {
        int n,a,b,fa,fb,f;
        scanf("%d%d%d%d%d%d",&n,&a,&b,&f,&fa,&fb);
        solve.init();
        FOR(i,1,n) scanf("%d",val+i), solve.addedge(0,i,val[i],0), solve.addedge(0,i+n,INF,f), solve.addedge(i+n,2*n+1,val[i],0);
        FOR(i,1,n) {
            if (i<n) solve.addedge(i,i+1,INF,0);
            if (i<n-a) solve.addedge(i,i+n+a+1,INF,fa);
            if (i<n-b) solve.addedge(i,i+n+b+1,INF,fb);
        }
        printf("%d
    ",solve.mincostmaxflow(0,2*n+1,2*n+2).first);
        return 0;
    }
    View Code
  • 相关阅读:
    sql server 跨IP库更新表字段(OPENDATASOURCE 、update)
    sql server 开启一个事务
    ARMv8 汇编指令集查询
    开源操作系统项目
    Cmake使用教程交叉编译
    开源机器人项目
    网络通信协议之粘包问题
    开源图像处理计算机视觉
    开源机器学习项目
    C语言中的回调函数
  • 原文地址:https://www.cnblogs.com/lishiyao/p/6548239.html
Copyright © 2011-2022 走看看