• BZOJ 1391: [Ceoi2008]order


    Description

    有一些任务,需要用到一些机器,可以买可以租,问最大获利.

    Solution

    网络流.

    最大权闭合子图模型.

    建图很简单就是S->机器,机器->任务,任务->T.

    如果没有租用的话,中间的是INF,不会割掉,加上租用就把容量变成租用的价格即可.

    这样求出来的割就是最小损失了,用总数减去即可.

    Code

    /**************************************************************
        Problem: 1391
        User: BeiYu
        Language: C++
        Result: Accepted
        Time:3864 ms
        Memory:55972 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
    using namespace std;
     
    #define debug(a) cout<<#a<<"="<<a<<" "
    const int INF = 0x3fffffff;
    const int N = 3650;
    const int M = 3000500;
     
    inline int in(int x=0,char ch=getchar()) { while(ch>'9' || ch<'0') ch=getchar();
        while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();return x; }
     
    int n,m;
    int val[N],ned[N],c[N];
     
    struct NetWork {
        vector< int > g[N];
        struct Edge { int fr,to,fl; }edge[M];
        int s,t,cnte,flow,tot;
        int cur[N],d[N],p[N];
         
        void AddEdge(int fr,int to,int fl) {
            g[fr].push_back(cnte),edge[cnte++]=(Edge){ fr,to,fl };
            g[to].push_back(cnte),edge[cnte++]=(Edge){ to,fr,0 };
        }
        void Build() {
            n=in(),m=in();
            s=0,t=2*m+n+6;
            for(int i=1,x;i<=n;i++) {
                for(x=in(),tot+=x,AddEdge(i,t,x),x=in();x--;) {
                    int idx=in(),cost=in();
                    AddEdge(n+idx,i,cost);
                }
            }
            for(int i=1;i<=m;i++) {
                c[i]=in();
                int x=n+i;
                AddEdge(s,x,c[i]);
            }
    //      for(int i=1;i<=m;i++) cout<<c1[i]<<" "<<c2[i]<<endl;
        }
        int BFS() {
            queue< int > q;
            memset(d,0xff,sizeof(d));
            q.push(s),d[s]=1;
            for(int x;!q.empty();) {
                x=q.front(),q.pop();
                for(int i=0,lm=g[x].size(),v;i<lm;i++) if(edge[g[x][i]].fl && d[(v=edge[g[x][i]].to)]==-1) {
                    d[v]=d[x]+1,q.push(v);
                }
            }return d[t]!=-1;
        }
        void Dinic() {
    //      debug(s),debug(t)<<endl;
            for(int u,k;BFS();) {
    //          cout<<"qwq"<<endl;debug(flow)<<endl;
                for(memset(cur,0,sizeof(cur)),u=s,k=0;;) {
                    if(u==t) {
                        int mine=0,minf=INF;
                        for(int i=0;i<k;i++) if(edge[p[i]].fl<minf) minf=edge[p[i]].fl,mine=i;
                        for(int i=0;i<k;i++) edge[p[i]].fl-=minf,edge[p[i]^1].fl+=minf;
    //                  for(int i=0;i<k;i++) cout<<edge[p[i]].fr<<"-->";cout<<endl;
    //                  debug(minf)<<endl;
                        k=mine,flow+=minf,u=edge[p[mine]].fr;
                    }
                    for(int &i=cur[u],lm=g[u].size(),v;i<lm;i++) 
                        if(edge[g[u][i]].fl && d[(v=edge[g[u][i]].to)]==d[u]+1) break;
                    if(cur[u]<(int)g[u].size()) {
                        p[k++]=g[u][cur[u]],u=edge[g[u][cur[u]]].to;
                    } else {
                        if(!k) break;
                        d[u]=-1,u=edge[p[--k]].fr;
                    }
                }
            }
        }
        int Maxflow() {
            flow=0,tot=0;
            Build();
            Dinic();
            return tot-flow;
        }
    }py;
     
    int main() {
        cout<<py.Maxflow()<<endl;
        return 0;
    }
    

      

  • 相关阅读:
    使用cordova,监听安卓机物理返回按键,实现退出程序的功能
    使用cordova network-information 插件监听手机网络状态
    使用cordova,使html5也能像IOS,Android那样可以 调取手机的相机拍照功能
    使用canvas给图片添加水印, canvas转换base64,,canvas,图片,base64等转换成二进制文档流的方法,并将合成的图片上传到服务器,
    phpStudy的安装和配置
    小程序入坑(一)---如何引入iconfont 字体图标
    HTML5 原生API input file 来实现多图上传,并大图预览
    webpack引入全局jQuery
    前端滑动分页获取数据(jQuery)
    开源蚂蚁笔记自建服务器
  • 原文地址:https://www.cnblogs.com/beiyuoi/p/6390070.html
Copyright © 2020-2023  润新知