您的位置:首页 > 其它

【bzoj1391】【Ceoi2008】【Order】【最小割】

2016-03-27 18:30 399 查看

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<iostream>
#include<cstring>
#include<cstdio>
#define N 3000
#define M 1500000
#define INF 2100000000
using namespace std;
int point
,next[M*2],n,m,cnt(1),k,a,b,c;
int dis
,cur
,gap
,pre
,s,T,sum,mn;
struct use{int st,en,v;}e[M*2];
bool f;
void add(int x,int y,int v){
//cout<<x<<' '<<y<<' '<<v<<endl;
next[++cnt]=point[x];point[x]=cnt;e[cnt].st=x;e[cnt].en=y;e[cnt].v=v;
next[++cnt]=point[y];point[y]=cnt;e[cnt].st=y;e[cnt].en=x;e[cnt].v=0;
}
int isap(){
int u(1),i,ans(0);gap[0]=T;
for (i=1;i<=T;i++) cur[i]=point[i];
while(dis[1]<T){
f=false;
for (i=cur[u];i;i=next[i])
if (e[i].v&&dis[e[i].en]+1==dis[u]){f=true;cur[u]=i;break;}
if (f){
u=e[i].en;pre[u]=i;
if (u==T){
mn=INF;
for (i=T;i!=1;i=e[pre[i]].st) mn=min(mn,e[pre[i]].v);
ans+=mn;
for (i=T;i!=1;i=e[pre[i]].st) e[pre[i]].v-=mn,e[pre[i]^1].v+=mn;
u=1;
}
}
else{
gap[dis[u]]--;if (!gap[dis[u]]) return ans;
for (mn=T+1,i=point[u];i;i=next[i]) if (e[i].v)mn=min(mn,dis[e[i].en]);
dis[u]=mn+1;gap[dis[u]]++;cur[u]=point[u];if (u!=1)u=e[pre[u]].st;
}
}
return ans;
}
int main(){
scanf("%d%d",&n,&m);T=n+m+2;
for (int i=1;i<=n;i++){
scanf("%d%d",&a,&s);
add(1,i+1,a);sum+=a;
for (int j=1;j<=s;j++){scanf("%d%d",&k,&c);add(i+1,k+n+1,c);}
}
for (int i=1;i<=m;i++){scanf("%d",&c);add(i+n+1,T,c);}
printf("%d\n",sum-isap());
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: