您的位置:首页 > 其它

bzoj 1497: [NOI2006]最大获利

2016-03-13 06:35 302 查看
#include<cstdio>
#include<iostream>
#include<cstring>
#define M 100008
#define inf 2139062143
using namespace std;
int T,head[M],next[10*M],u[10*M],v[10*M],d[M],n,m,cnt=1,ans,q[2*M],sum;
void jia(int a1,int a2,int a3)
{
cnt++;
u[cnt]=a2;
v[cnt]=a3;
next[cnt]=head[a1];
head[a1]=cnt;
}
bool bfs()
{
memset(d,0,sizeof(int)*(T+2));
int h=0,t=1;
q[1]=0;
d[0]=1;
for(;h<t;)
{
h++;
int p=q[h];
for(int i=head[p];i;i=next[i])
if(!d[u[i]]&&v[i])
{
d[u[i]]=d[p]+1;
if(d[T])
return 1;
t++;
q[t]=u[i];
}
}
return 0;
}
int dinic(int s,int f)
{
if(s==T)
return f;
int rest=f;
for(int i=head[s];i&&rest;i=next[i])
if(v[i]&&d[u[i]]==d[s]+1)
{
int now=dinic(u[i],min(rest,v[i]));
if(!now)
d[u[i]]=0;
v[i]-=now;
v[i^1]+=now;
rest-=now;
}
return f-rest;
}
int main()
{
scanf("%d%d",&n,&m);
T=n+m+1;
for(int i=1;i<=n;i++)
{
int a1;
scanf("%d",&a1);
jia(i,T,a1);
jia(T,i,0);
}
for(int i=1;i<=m;i++)
{
int a1,a2,a3,a4;
a3=n+i;
scanf("%d%d%d",&a1,&a2,&a4);
sum+=a4;
jia(a3,a1,inf);
jia(a1,a3,0);
jia(a3,a2,inf);
jia(a2,a3,0);
jia(0,a3,a4);
jia(a3,0,0);
}
for(;bfs();)
ans+=dinic(0,inf);
printf("%d\n",sum-ans);
return 0;
}


最小割 站向汇点连容量为费用的边,源点向用户群连容量为获利的边,用户群与站之间有关联的连容量为inf的边,跑最小割,用总收益减去即为答案。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: