BZOJ 1391: [Ceoi2008]order
题目大意:
完成一个任务能获得钱,但是需要租用多个机器或者购买多个机器来完成,当然也可以不完成。
求最大利润。
题解:
最小割,比较显然。
代码:
#include<cstdio> #include<algorithm> using namespace std; int n,m,S,T,cnt,last[1205*2],q[1205*2],cur[1205*2],h[1205*2]; struct node{ int to,next,cap; }e[1205*1205*2]; void add(int a,int b,int c){ e[++cnt].to=b; e[cnt].cap=c; e[cnt].next=last[a]; last[a]=cnt; } void ADD(int a,int b,int c){ add(a,b,c); add(b,a,0); } int bfs(){ for (int i=1; i<=T; i++) h[i]=-1; h[S]=0; int head=0,tail=1; q[tail]=S; while (head<tail){ int x=q[++head]; for (int i=last[x]; i; i=e[i].next){ int V=e[i].to; if (e[i].cap && h[V]==-1){ h[V]=h[x]+1; q[++tail]=V; } } } return h[T]!=-1; } int dfs(int x,int low){ if (x==T) return low; int used=0; for (int i=cur[x]; i; i=e[i].next){ int V=e[i].to; if (e[i].cap && h[V]==h[x]+1){ int w=dfs(V,min(e[i].cap,low-used)); e[i].cap-=w; e[i^1].cap+=w; used+=w; cur[x]=i; if (low==used) return low; } } if (!used) h[x]=-1; return used; } int dinic(){ int ans=0; while (bfs()){ for (int i=1; i<=T; i++) cur[i]=last[i]; ans+=dfs(S,1e9); } return ans; } int main(){ cnt=1; scanf("%d%d",&n,&m); S=n+m+1,T=n+m+2; int ans=0; for (int i=1; i<=n; i++){ int x,y; scanf("%d%d",&x,&y); ans+=x; ADD(S,i,x); for (int j=1; j<=y; j++){ int x,y; scanf("%d%d",&x,&y); ADD(i,n+x,y); } } for (int i=1; i<=m; i++){ int x; scanf("%d",&x); ADD(n+i,T,x); } printf("%d\n",ans-dinic()); return 0; }