• [BZOJ 1221][HNOI2001]软件开发(费用流)


    Description

    某软件公司正在规划一项n天的软件开发计划,根据开发计划第i天需要ni个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的服务,其中一项服务就是要为每个开发人员每天提供一块消毒毛巾,这种消毒毛巾使用一天后必须再做消毒处理后才能使用。消毒方式有两种,A种方式的消毒需要a天时间,B种方式的消毒需要b天(b>a),A种消毒方式的费用为每块毛巾fA, B种消毒方式的费用为每块毛巾fB,而买一块新毛巾的费用为f(新毛巾是已消毒的,当天可以使用);而且f>fA>fB。公司经理正在规划在这n天中,每天买多少块新毛巾、每天送多少块毛巾进行A种消毒和每天送多少块毛巾进行B种消毒。当然,公司经理希望费用最低。你的任务就是:为该软件公司计划每天买多少块毛巾、每天多少块毛巾进行A种消毒和多少毛巾进行B种消毒,使公司在这项n天的软件开发中,提供毛巾服务的总费用最低。

    Solution

    据说是非常经典的建图方式?网络流24题——餐巾计划问题

    把每一天拆为脏的餐巾与需要的餐巾…

    BY BYVOID:
    把每天分为二分图两个集合中的顶点Xi,Yi,建立附加源S汇T。
    1、从S向每个Xi连一条容量为ri,费用为0的有向边。
    2、从每个Yi向T连一条容量为ri,费用为0的有向边。
    3、从S向每个Yi连一条容量为无穷大,费用为p的有向边。
    4、从每个Xi向Xi+1(i+1<=N)连一条容量为无穷大,费用为0的有向边。
    5、从每个Xi向Yi+m(i+m<=N)连一条容量为无穷大,费用为f的有向边。
    6、从每个Xi向Yi+n(i+n<=N)连一条容量为无穷大,费用为s的有向边。
    求网络最小费用最大流,费用流值就是要求的最小总花费。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<queue>
    #define INF 0x3f3f3f3f
    using namespace std;
    int n,a,b,f,fa,fb,s,t,head[2005],c[2005],dis[2005],pre[2005],cnt=0;
    bool inq[2005];
    struct Node
    {
        int next,from,to,cap,w;
    }Edges[50005];
    int read()
    {
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){
            if(c=='-')f=-1;c=getchar();
        }
        while(c>='0'&&c<='9'){
            x=x*10+c-'0';c=getchar();
        }
        return x*f;
    }
    void addedge(int u,int v,int c,int w)
    {
        Edges[cnt].next=head[u];
        head[u]=cnt;
        Edges[cnt].from=u;
        Edges[cnt].to=v;
        Edges[cnt].cap=c;
        Edges[cnt++].w=w;
    }
    void insert(int u,int v,int c,int w)
    {
        addedge(u,v,c,w);
        addedge(v,u,0,-w);
    }
    queue<int>q;
    int MCMF()
    {
        int cost=0,flow=0;
        while(1)
        {
            memset(c,0,sizeof(c));
            memset(dis,0x3f,sizeof(dis));
            q.push(s);
            inq[s]=1,dis[s]=0,c[s]=INF,pre[s]=-1;
            while(!q.empty())
            {
                int u=q.front();
                q.pop(),inq[u]=0;
                for(int i=head[u];~i;i=Edges[i].next)
                {
                    int v=Edges[i].to;
                    if(dis[v]>dis[u]+Edges[i].w&&Edges[i].cap>0)
                    {
                        dis[v]=dis[u]+Edges[i].w;
                        c[v]=min(c[u],Edges[i].cap);
                        pre[v]=i;
                        if(!inq[v])inq[v]=1,q.push(v);
                    }
                }
            }
            if(!c[t])break;
            cost+=c[t]*dis[t];
            flow+=c[t];
            int p=t;
            while(pre[p]!=-1)
            {
                Edges[pre[p]].cap-=c[t];
                Edges[pre[p]^1].cap+=c[t];
                p=Edges[pre[p]].from;
            }
        }
        return cost;
    }
    int main()
    {
        memset(head,-1,sizeof(head));
        n=read(),a=read(),b=read(),f=read(),fa=read(),fb=read();
        s=0,t=2*n+1;
        for(int i=1;i<=n;i++)
        {
            int x=read();
            insert(s,i,x,0);
            insert(i+n,t,x,0);
            insert(s,i+n,INF,f);
            if(i+a+1<=n)
            insert(i,i+a+1+n,INF,fa);
            if(i+b+1<=n)
            insert(i,i+b+1+n,INF,fb);
            if(i+1<=n)
            insert(i,i+1,INF,0);
        }
        printf("%d
    ",MCMF());
        return 0;
    } 
  • 相关阅读:
    学习Java的Day02
    学习Java的Day01
    多线程的了解
    几个MQ的区别
    HTML5——存储(cookie、localStorage、sessionStorage)的区别
    dubbo mock配置
    Springboot分布式,excel导出,运用POI导出,前端用的jsp
    oracle 添加字段和添加注释
    可以重复的Map:IdentityHashMap
    数组转list问题
  • 原文地址:https://www.cnblogs.com/Zars19/p/6869515.html
Copyright © 2020-2023  润新知