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;
}

  

posted @ 2017-02-11 21:55  北北北北屿  阅读(174)  评论(0编辑  收藏  举报