BZOJ1391: [Ceoi2008]order

来源:互联网 发布:淘宝青少年男装 编辑:程序博客网 时间:2024/05/18 03:27

[Ceoi2008]order

  • Description

    有N个工作,M种机器,每种机器你可以租或者买过来. 每个工作包括若干道工序,每道工序需要某种机器来完成,你可以通过购买或租用机器来完成。 现在给出这些参数,求最大利润。

构图方法

  • 若不考虑租借,则是裸最大权闭合子图。那么这题就需要考虑如何修改建图方式,使得“可以选x的时候可以不选y,但要付出一定代价”。
  • 只需将中间相邻的边权为INF的边,容量改为租借费用即可。
  • ①:S向每个工作连边,容量为获益值;
    ②:每个机器向T连边,容量为购买费用;
    ③:每个工作向所需机器连边,容量为租借费用。
    PS:要加当前弧优化!

【代码】

#include <cstdio>#include <iostream>#include <queue>#include <vector>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#define N 2405#define M 2884805#define INF 1000000001using namespace std;typedef long long ll;typedef pair<ll,ll> pa;int read(){    int x=0,f=1;char ch=getchar();    while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}    while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}    return x*f;}int n,m,cnt=1,S,T,ans;int b[M],p[N],nextedge[M],w[M],cur[N];int Level[N];void Add(int x,int y,int z){    cnt++;    b[cnt]=y;    nextedge[cnt]=p[x];    p[x]=cnt;    w[cnt]=z;}void Anode(int x,int y,int z){    Add(x,y,z);Add(y,x,0);}void Input_Init(){    T=n+m+1;    for(int i=1;i<=n;i++)    {        static int x,y,z,num;        x=read(),num=read();        Anode(0,i,x);ans+=x;        while(num--)        {            y=read(),z=read();            Anode(i,n+y,z);        }    }    for(int i=1;i<=m;i++)    {        static int x;        x=read();        Anode(n+i,T,x);    }}bool Bfs(){    queue<int>q;    q.push(S);    for(int i=0;i<=T;i++) Level[i]=0;    Level[S]=1;    while(!q.empty())    {        int k=q.front();q.pop();        for(int i=p[k];i;i=nextedge[i])        {            int v=b[i],f=w[i];            if(!Level[v]&&f)            {                Level[v]=Level[k]+1;                q.push(v);            }        }    }    return Level[T];}int Dfs(int x,int maxf){    if(x==T||!maxf) return maxf;    int rtn=0;    for(int i=cur[x];i&&maxf>rtn;i=nextedge[i])    {        int v=b[i],f=w[i];        if(Level[v]==Level[x]+1&&f)        {            f=Dfs(v,min(maxf-rtn,f));            w[i]-=f;w[i^1]+=f;            if(w[i]>0) cur[x]=i;            rtn+=f;        }    }    if(!rtn) Level[x]=0;    return rtn;}void Dinic(){    while(Bfs())    {        for(int i=0;i<=T;i++) cur[i]=p[i];        ans-=Dfs(S,INF);    }       printf("%d\n",ans);}int main(){    n=read();m=read();    Input_Init();    Dinic();    return 0;}
0 0
原创粉丝点击