【BZOJ-1391】order 最小割 + 最大全闭合图
1391: [Ceoi2008]order
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1334 Solved: 405
[Submit][Status][Discuss]
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
100 2
1 30
2 20
100 2
1 40
3 80
50
80
110
Sample Output
50
HINT
Source
Solution
这玩意叫啥来着? 最大权闭合图? 反正是个裸题
于是正常暴力构图,正确性很显然:
假设任务在S一侧,机器在T一侧。
如果任务A在S割且机器B也在S割,那么割掉的是边B-->T,这代表购买机器的代价。
如果任务A在T割且机器B也在T割,那么割掉的是边S-->A,这代表舍弃任务的代价。
如果任务A在S割但机器B在T割,那么割掉的是边A-->B,这代表租用机器的代价。
Code
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<queue> using namespace std; int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define maxm 3000010 #define maxn 3010 int n,m,tot; struct EdgeNode{int next,to,cap;}edge[maxm]; int head[maxn],cnt=1; void add(int u,int v,int w) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].cap=w;} void insert(int u,int v,int w) {add(u,v,w); add(v,u,0);} #define inf 0x7fffffff int dis[maxn],cur[maxn],S,T; bool bfs() { queue<int>q; for (int i=S; i<=T; i++) dis[i]=-1; q.push(S); dis[S]=0; while (!q.empty()) { int now=q.front(); q.pop(); for (int i=head[now]; i; i=edge[i].next) if (edge[i].cap && dis[edge[i].to]==-1) dis[edge[i].to]=dis[now]+1,q.push(edge[i].to); } return dis[T]!=-1; } int dfs(int x,int low) { if (x==T) return low; int used=0,w; for (int i=cur[x]; i; i=edge[i].next) if (edge[i].cap && dis[edge[i].to]==dis[x]+1) { w=dfs(edge[i].to,min(edge[i].cap,low-used)); edge[i].cap-=w; edge[i^1].cap+=w; used+=w; if (edge[i].cap) cur[x]=i; if (low==used) return used; } if (!used) dis[x]=-1; return used; } int dinic() { int tmp=0; while (bfs()) { for (int i=S; i<=T; i++) cur[i]=head[i]; tmp+=dfs(S,inf); } return tmp; } int main() { n=read(),m=read(); S=0,T=n+m+1; for (int x,y,i=1; i<=n; i++) { x=read(),y=read(); tot+=x; insert(S,i,x); for (int z,c,j=1; j<=y; j++) z=read(),c=read(),insert(i,z+n,c); } for (int x,i=1; i<=m; i++) x=read(),insert(i+n,T,x); printf("%d\n",tot-dinic()); return 0; }
——It's a lonely path. Don't make it any lonelier than it has to be.