原文链接http://www.cnblogs.com/zhouzhendong/p/8371052.html


题目传送门 - BZOJ1497


题意概括

  有n个站要被建立。

  建立第i个站的花费为pi。

  特别的,当第Ai和Bi都被建立时可以得到收益Ci.

  问最大收益为多少。


题解

  做法特别巧妙。

  我们假装所有的Ci都可以被取到。

  然后我们考虑至少要失去多少。

  我们对于所有站i,建立S->i的边,边权为Pi.

  对于所有的i,建立Ai->i+n,Bi->i+n边权为INF,以及i+n->T,边权为Ci。

  然后要失去的价值要尽量小,于是我们只需要求得最小割即可。

  由于最小割=最大流,所以SAP跑一跑即可。


代码

#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
const int N=55005,M=N*3*2,INF=1e9;
struct edge{
int x,y,cap,flow,nxt;
};
struct gragh{
int cnt,fst[N],dist[N],n,S,T,num[N],cur[N],p[N];
int q[N],head,tail;
edge e[M];
void set(int _S,int _T,int _n){
S=_S,T=_T,n=_n,cnt=1;
memset(fst,0,sizeof fst);
}
void add(int a,int b,int c){
cnt++;
e[cnt].x=a,e[cnt].y=b,e[cnt].cap=c,e[cnt].flow=0;
e[cnt].nxt=fst[a],fst[a]=cnt;
cnt++;
e[cnt].x=b,e[cnt].y=a,e[cnt].cap=0,e[cnt].flow=0;
e[cnt].nxt=fst[b],fst[b]=cnt;
}
void bfs(){
memset(dist,-1,sizeof dist);
head=tail=dist[T]=0;
q[++tail]=T;
while (head<tail)
for (int x=q[++head],y,i=fst[x];i;i=e[i].nxt)
if ((i&1)&&dist[y=e[i].y]==-1)
dist[q[++tail]=y]=dist[x]+1;
for (int i=1;i<=n;i++)
if (dist[i]==-1)
dist[i]=n;
}
void init(){
bfs();
memset(num,0,sizeof num);
for (int i=1;i<=n;i++)
num[dist[i]]++,cur[i]=fst[i];
}
int Augment(int &x){
int ex_flow=INF;
for (int i=T;i!=S;i=e[p[i]].x)
if (e[p[i]].cap-e[p[i]].flow<=ex_flow)
ex_flow=e[p[i]].cap-e[p[i]].flow,x=e[p[i]].x;
for (int i=T;i!=S;i=e[p[i]].x)
e[p[i]].flow+=ex_flow,e[p[i]^1].flow-=ex_flow;
return ex_flow;
}
int ISAP(){
int x=S,y,MaxFlow=0;
init();
while (dist[S]<n){
if (x==T){
MaxFlow+=Augment(x);
continue;
}
bool found=0;
for (int i=cur[x];i;i=e[i].nxt)
if (dist[y=e[i].y]+1==dist[x]&&e[i].cap>e[i].flow){
cur[x]=p[y]=i,x=y,found=1;
break;
}
if (!found){
int d=n+1;
for (int i=fst[x];i;i=e[i].nxt)
if (e[i].cap>e[i].flow)
d=min(d,dist[e[i].y]+1);
if (!--num[dist[x]])
return MaxFlow;
num[dist[x]=d]++,cur[x]=fst[x],x=x==S?x:e[p[x]].x;
}
}
return MaxFlow;
}
}g;
int n,m,S,T,p[5005],A[50005],B[50005],C[50005];
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&p[i]);
int total=0;
for (int i=1;i<=m;i++)
scanf("%d%d%d",&A[i],&B[i],&C[i]),total+=C[i];
S=n+m+1,T=n+m+2;
g.set(S,T,n+m+2);
for (int i=1;i<=n;i++)
g.add(S,i,p[i]);
for (int i=1;i<=m;i++){
g.add(A[i],i+n,INF);
g.add(B[i],i+n,INF);
g.add(i+n,T,C[i]);
}
printf("%d",total-g.ISAP());
return 0;
}

  

BZOJ1497 [NOI2006]最大获利 网络流 最小割 SAP的更多相关文章

  1. bzoj1497: [NOI2006]最大获利(最小割)

    传送门 第一眼看去:好难 第二眼:不就是个裸的最大权闭合子图么…… 我们从源点向所有用户连边,容量为收益,用户向自己的中转站连边,容量为INF,中转站向汇点连边,容量为费用 那么总收益-最小割就是答案 ...

  2. Bzoj1497 [NOI2006]最大获利

    Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 4449  Solved: 2181 Description 新的技术正冲击着手机通讯市场,对于各大运营商来 ...

  3. 【题解】 bzoj3894: 文理分科 (网络流/最小割)

    bzoj3894,懒得复制题面,戳我戳我 Solution: 首先这是一个网络流,应该还比较好想,主要就是考虑建图了. 我们来分析下题面,因为一个人要么选文科要么选理科,相当于两条流里面割掉一条(怎么 ...

  4. 【bzoj3774】最优选择 网络流最小割

    题目描述 小N手上有一个N*M的方格图,控制某一个点要付出Aij的代价,然后某个点如果被控制了,或者他周围的所有点(上下左右)都被控制了,那么他就算是被选择了的.一个点如果被选择了,那么可以得到Bij ...

  5. 【bzoj1143】[CTSC2008]祭祀river Floyd+网络流最小割

    题目描述 在遥远的东方,有一个神秘的民族,自称Y族.他们世代居住在水面上,奉龙王为神.每逢重大庆典, Y族都会在水面上举办盛大的祭祀活动.我们可以把Y族居住地水系看成一个由岔口和河道组成的网络.每条河 ...

  6. 【bzoj1797】[Ahoi2009]Mincut 最小割 网络流最小割+Tarjan

    题目描述 给定一张图,对于每一条边询问:(1)是否存在割断该边的s-t最小割 (2)是否所有s-t最小割都割断该边 输入 第一行有4个正整数,依次为N,M,s和t.第2行到第(M+1)行每行3个正 整 ...

  7. 【bzoj1976】[BeiJing2010组队]能量魔方 Cube 网络流最小割

    题目描述 一个n*n*n的立方体,每个位置为0或1.有些位置已经确定,还有一些需要待填入.问最后可以得到的 相邻且填入的数不同的点对 的数目最大. 输入 第一行包含一个数N,表示魔方的大小. 接下来 ...

  8. 【bzoj4177】Mike的农场 网络流最小割

    题目描述 Mike有一个农场,这个农场n个牲畜围栏,现在他想在每个牲畜围栏中养一只动物,每只动物可以是牛或羊,并且每个牲畜围栏中的饲养条件都不同,其中第i个牲畜围栏中的动物长大后,每只牛可以卖a[i] ...

  9. 【bzoj3438】小M的作物 网络流最小割

    原文地址:http://www.cnblogs.com/GXZlegend/p/6801522.html 题目描述 小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物 ...

随机推荐

  1. ubuntu 安装配置 mysql

    注:上一篇内容是直接使用虚拟机配置好的mysql数据库, 阿里云服务器的默认是没有mysql的. 下载安装 mysql: sudo apt-get update sudo apt-get instal ...

  2. Js操作Array数组

    之前写过一篇文章,但是很模糊,不过却给我提供了一个思路,所以没有删除,这次写的是一个完善版本! 因为在很多的时候我们在选中了几行数据,然后存放在Array中,如下图: 看下控制台的数据 我双击了这两个 ...

  3. 如何获取STM32 MCU的唯一ID

    前段时间由于应用需要对产品授权进行限制,所以研究了一下有关STM32 MCU的唯一ID的资料,并最终利用它实现了我们的目标. 1.基本描述 在STM32的全系列MCU中均有一个96位的唯一设备标识符. ...

  4. django配置一个网站建设

    第一步: 安装数据库MySQL,也可以使用pycharm自带的数据库sqllite,大项目要使用数据库.安装请参考上篇. 数据库在pycharm中驱动设置,setting文件中修改驱动文件密码等信息. ...

  5. Spring Boot的Listener机制的用法和实现原理详解

    之前在介绍了在spring-boot启动过程中调用runner的原理,今天我们介绍另外一种可以实现相似功能的机制:spring-boot的Listener机制. 通过注册Listener,可以实现对于 ...

  6. Windows Internals 笔记——线程局部存储区

    1.由于C/C++运行库是在多线程应用程序出现的许多年前设计的,因此运行库中的大多数函数是为单线程应用程序设计的. 2.当应用程序第一次调用_tcstok_s的时候该函数将传入的字符串地址保存在它自己 ...

  7. C++ Primer 笔记——固有的不可移植的特性

    1.为了支持底层编程,C++定义了一些固有的不可移植的特性,所谓不可移植特性是指因机器而异的特性. 2.一个位域中含有一定数量的二进制位,位域在内存中的布局是机器相关的.位域的类型必须是整型或枚举类型 ...

  8. Oracle logminer 日志挖掘

    Table of Contents 1. LOGMNR简介 2. 创建数据字典 2.1. 外部文件存储数据字典 2.2. redo log 存储数据字典 3. 添加需要分析的文件 4. 开始分析文件 ...

  9. 调试阶段 获取微信小程序openid

    wx.login({ success: function(res) { //首先获取用户code //res.code wx.request({ url: 'https://api.weixin.qq ...

  10. PAT Basic 1069. 微博转发抽奖(20)

    小明PAT考了满分,高兴之余决定发起微博转发抽奖活动,从转发的网友中按顺序每隔N个人就发出一个红包.请你编写程序帮助他确定中奖名单. 输入格式: 输入第一行给出三个正整数M(<= 1000).N ...