BZOJ1391: [Ceoi2008]order

Description

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

Input

第一行给出 N,M(1<=N<=1200,1<=M<=1200) 下面将有N块数据,每块数据第一行给出完成这个任务能赚到的钱(其在[1,5000])及有多少道工序 接下来若干行每行两个数,分别描述完成工序所需要的机器编号及租用它的费用(其在[1,20000]) 最后M行,每行给出购买机器的费用(其在[1,20000])

Output

最大利润

Sample Input

2 3
100 2
1 30
2 20
100 2
1 40
3 80
50
80
110

Sample Output

50

HINT

最小割裸题。。。
#include<cstdio>
#include<cctype>
#include<queue>
#include<cmath>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
    if(head==tail) {
        int l=fread(buffer,1,BufferSize,stdin);
        tail=(head=buffer)+l;
    }
    return *head++;
}
inline int read() {
    int x=0,f=1;char c=Getchar();
    for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
    return x*f;
}
const int maxn=3010;
const int maxm=3000010;
const int inf=1e9;
struct ISAP{
    struct tedge{int x,y,w,next;}adj[maxm];int ms,fch[maxn];
    int d[maxn],s[maxn],cur[maxn],gap[maxn],n,top;
    void init(int n){
        this->n=n;ms=0;top=0;
        memset(d,-1,sizeof(d));
        memset(fch,-1,sizeof(fch));
        return;
    }
    void AddEdge(int u,int v,int w){
        adj[ms]=(tedge){u,v,w,fch[u]};fch[u]=ms++;
        adj[ms]=(tedge){v,u,0,fch[v]};fch[v]=ms++;
        return;
    }
    void bfs(){
        queue<int>Q;Q.push(n);d[n]=0;
        while(!Q.empty()){
            int u=Q.front();Q.pop();
            for(int i=fch[u];i!=-1;i=adj[i].next){
                int v=adj[i].y;
                if(d[v]==-1) d[v]=d[u]+1,Q.push(v);
            }
        } return;
    }
    int solve(int S,int T){
        n=T;bfs();int k=S,i,flow=0;
        for(i=0;i<=n;i++) cur[i]=fch[i],gap[d[i]]++;
        while(d[S]<n){
            if(k==n){
                int mi=inf,pos;
                for(i=0;i<top;i++) if(adj[s[i]].w<mi) mi=adj[s[i]].w,pos=i;
                for(i=0;i<top;i++) adj[s[i]].w-=mi,adj[s[i]^1].w+=mi;
                flow+=mi;top=pos;k=adj[s[top]].x;
            }
            for(i=cur[k];i!=-1;i=adj[i].next){
                int v=adj[i].y;
                if(adj[i].w&&d[k]==d[v]+1){cur[k]=i;k=v;s[top++]=i;break;}
            }
            if(i==-1){
                int lim=n;
                for(i=fch[k];i!=-1;i=adj[i].next){
                    int v=adj[i].y;
                    if(adj[i].w&&d[v]<lim) lim=d[v],cur[k]=i;
                } if(--gap[d[k]]==0) break;
                d[k]=lim+1;gap[d[k]]++;
                if(k!=S) k=adj[s[--top]].x;
            }
        } return flow;
    }
}sol;
int c[maxn];
int main() {
    int n=read(),m=read();int sum=0;
    sol.init(n+m+2);int S=n+m+1,T=S+1;
    rep(i,1,n) {
        sum+=(c[i]=read());int k=read();
        sol.AddEdge(S,i,c[i]);
        while(k--) {
            int x=read(),v=read();
            sol.AddEdge(i,n+x,v);
        }
    }
    rep(i,1,m) sol.AddEdge(i+n,T,read());
    printf("%d\n",sum-sol.solve(S,T));
    return 0;
}
View Code

 

posted @ 2016-03-17 17:00  wzj_is_a_juruo  阅读(179)  评论(0编辑  收藏  举报