您的位置:首页 > 其它

【BZOJ 1391】[Ceoi2008]order 最小割

2017-01-17 21:21 309 查看
建图s向每个任务建边,容量为收益,任务向机器建边,容量为租用机器花费,机器向汇点建边,容量为购买机器的费用,然后跑最小割,每割掉一条边就相当于放弃这个收益或者选择这个花销。
#include<cstdio>
#include<cstring>
#include<iostream>
#define maxn 4000020
#define N 2405
using namespace std;
void read(int& x){
x=0;char c=getchar();int f=1;
for(;c>'9'||c<'0';c=getchar())if(c=='-')f=-1;
for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0';
x*=f;
}
int head
,tot,n,m,q[N*2],ans,s,t,last
,h
;
struct edge{int v,next,w;}e[maxn];
void adde(int a,int b,int c){
e[tot].v=b,e[tot].next=head[a],e[tot].w=c;head[a]=tot++;
e[tot].v=a,e[tot].next=head[b],e[tot].w=0;head[b]=tot++;
}
bool bfs(){
int l=0,r=1;q[l]=s;
for(int i=s;i<=t;i++)h[i]=-1;h[s]=0;
while(l<r){
int u=q[l++];
for(int v,i=head[u];i!=-1;i=e[i].next)
if(h[v=e[i].v]==-1&&e[i].w){
h[v]=h[u]+1;
q[r++]=v;
}
}
return h[t]!=-1;
}
int dfs(int u,int f){
if(u==t)return f;
int used=0,w;
for(int v,i=last[u];i!=-1;i=e[i].next)
if(h[v=e[i].v]==h[u]+1&&e[i].w){
last[u]=i;
w=min(f-used,e[i].w);
w=dfs(v,w);
used+=w;e[i].w-=w,e[i^1].w+=w;
if(used==f)return used;
}
if(!used)h[u]=-1;
return used;
}
void dinic(){
while(bfs()){
for(int i=s;i<=t;i++)last[i]=head[i];
ans-=dfs(s,1e9);
}
}

int main(){
memset(head,-1,sizeof(head));
read(n),read(m);
t=n+m+1;
for(int a,b,c,d,i=1;i<=n;i++){
read(a),read(b);
adde(s,i,a);ans+=a;
for(int j=1;j<=b;j++){
read(c),read(d);
adde(i,c+n,d);
}
}
for(int a,i=1;i<=m;i++){
read(a);
adde(n+i,t,a);
}
dinic();
printf("%d",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: