题目描述
有 (N) 个工作,(M) 种机器,每种机器可以租或者买。每个工作包括若干道工序,每道工序需要某种机器来完成。
你需要最大化利益。
输入格式
第一行给出 (N,M)。
接下来若干行描述一个工作,对于每个工作,第一行给定 (x_i) 和 (t_i),分别表示此工作的收入和工序数。
后面 (t_i) 行,每行两个整数 (a_{ij}) 和 (b_{ij}),分别表示此工序需要的机器和此工作租用此机器的费用。
最后 (M) 行,每行一个正整数表示购买机器的费用 (y_i)。
输出格式
最大利润
基本上是最大权闭合子图的模板
租借操作就把inf改权值
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=2505,M=N*N,inf=1<<30;
int nxt[M],head[N],go[M],edge[M],tot=1;
inline void add(int u,int v,int w){
nxt[++tot]=head[u],head[u]=tot,go[tot]=v,edge[tot]=w;
nxt[++tot]=head[v],head[v]=tot,go[tot]=u,edge[tot]=0;
}
int n,m,s,t,maxflow;
int d[N],now[N];
bool bfs(){
queue<int>q;
memset(d,0,sizeof(d));
q.push(s); d[s]=1;
now[s]=head[s];
while(q.size()){
int u=q.front(); q.pop();
for(int i=head[u];i;i=nxt[i]){
int v=go[i];
if(edge[i]&&!d[v]){
q.push(v);
d[v]=d[u]+1;
now[v]=head[v];
if(v==t)return 1;
}
}
}
return 0;
}
int dinic(int u,int flow){
if(u==t)return flow;
for(int &i=now[u];i;i=nxt[i]){
int v=go[i];
if(edge[i]&&d[v]==d[u]+1){
int k=dinic(v,min(flow,edge[i]));
if(!k)d[v]=0;
else{
edge[i]-=k;
edge[i^1]+=k;
return k;
}
}
}
return 0;
}
signed main(){
cin>>n>>m;
s=0,t=n+m+1;
int ans=0;
for(int i=1,x,y,z;i<=n;i++){
scanf("%d%d",&x,&y);
add(s,i,x);
ans+=x;
while(y--){
scanf("%d%d",&x,&z);
add(i,n+x,z);
}
}
for(int i=1,x;i<=m;i++){
scanf("%d",&x);
add(n+i,t,x);
}
int flow=0;
while(bfs())
while(flow=dinic(s,inf))maxflow+=flow;
cout<<ans-maxflow<<endl;
}