码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 1497 最大获利

时间:2015-12-29 21:15:04      阅读:202      评论:0      收藏:0      [点我收藏+]

标签:

来自NOI2006,这玩意儿可能是历史上第一道网络流吧。

记住最大权闭合子图的建图方法。还要记住网络流的边数和点数绝不能轻易定!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#define maxv 55500
#define maxe 1000005
#define inf 0x7fffffff
using namespace std;
struct edge
{
int v,f,nxt;
}e[maxe];
int nume=1,n,m,x,y,z;
int g[maxv],s=0,t,sum=0,maxcut=0,dis[maxv];
inline void addedge(int u,int v,int f)
{
e[++nume].v=v;
e[nume].f=f;
e[nume].nxt=g[u];
g[u]=nume;
e[++nume].v=u;
e[nume].f=0;
e[nume].nxt=g[v];
g[v]=nume;
}
bool bfs()
{
queue <int> q;
memset(dis,-1,sizeof(dis));
q.push(s);
dis[s]=0;
while (!q.empty())
{
int head=q.front();
q.pop();
for (int i=g[head];i;i=e[i].nxt)
{
if ((e[i].f) && (dis[e[i].v]==-1))
{
q.push(e[i].v);
dis[e[i].v]=dis[head]+1;
}
}
}
if (dis[t]==-1) return false;
return true;
}
int dinic(int x,int low)
{
if (x==t)
return low;
else
{
int ret=0;
for (int i=g[x];low && i;i=e[i].nxt)
{
if (e[i].f && dis[e[i].v]==dis[x]+1)
{
int dd=dinic(e[i].v,min(e[i].f,low));
e[i].f=e[i].f-dd;
e[i^1].f=e[i^1].f+dd;
low=low-dd;
ret=ret+dd;
}
}
if (ret==0) dis[x]=-1;
return ret;
}
}
int main()
{
memset(g,0,sizeof(g));
scanf("%d%d",&n,&m);
t=n+m+1;
for (register int i=1;i<=n;i++)
{
scanf("%d",&x);
addedge(m+i,t,x);
}
for (register int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
sum=sum+z;
addedge(s,i,z);
addedge(i,m+x,inf);
addedge(i,m+y,inf);
}
while (bfs()==true)
maxcut=maxcut+dinic(s,inf);
printf("%d\n",sum-maxcut);
return 0;
}

BZOJ 1497 最大获利

标签:

原文地址:http://www.cnblogs.com/ziliuziliu/p/5086964.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!