您的位置:首页 > 其它

【BZOJ】1497 [NOI2006]最大获利

2017-03-23 12:03 429 查看
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1497

经典的网络流

割边表示舍弃该价值,所以可以把用户群的收益连向一边,建站的费用连向一边,中间把对应点连inf

这样的最小割就是最小舍弃的价值,加上总获利就是最大获利了

#include<stdio.h>
#include<algorithm>
#include<cstring>
#define cint const int &
#define inf 2333333
#define N 55005
using namespace std;

int tot=1,Q
,s
,cur
,lev
,tm
,ts,n,m,a,b,w,ans;

struct edge{int v,c,n;}e[N*6];
inline void push(cint u,cint v,cint c)
{
e[++tot]=(edge){v,c,s[u]};s[u]=tot;
e[++tot]=(edge){u,0,s[v]};s[v]=tot;
}

inline bool bfs()
{
memcpy(cur,s,sizeof(cur));
tm[Q[1]=1]=++ts;
for (int l=1,r=1;l<=r;l++) for (int i=s[Q[l]];i;i=e[i].n) if (e[i].c && tm[e[i].v]<ts)
tm[Q[++r]=e[i].v]=ts,lev[Q[r]]=lev[Q[l]]+1;
return tm[n+m+2]==ts;
}

int dfs(cint u,int c)
{
if (u==n+m+2) return c;
int g=0,tmp;
for (int i=cur[u];i && c;cur[u]=i,i=e[i].n) if (tm[e[i].v]==ts && lev[e[i].v]==lev[u]+1 && e[i].c && (tmp=dfs(e[i].v,min(c,e[i].c))))
g+=tmp,c-=tmp,e[i].c-=tmp,e[i^1].c+=tmp;
return g;
}

int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d",&w),push(1,i+1,w);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&w);
ans+=w;
push(a+1,n+1+i,inf);
push(b+1,n+1+i,inf);
push(n+1+i,n+m+2,w);
}
while (bfs()) for (int rt=dfs(1,inf);rt;rt=dfs(1,inf)) ans-=rt;
printf("%d",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: