【bzoj4177】Mike的农场 网络流最小割
题目描述
Mike有一个农场,这个农场n个牲畜围栏,现在他想在每个牲畜围栏中养一只动物,每只动物可以是牛或羊,并且每个牲畜围栏中的饲养条件都不同,其中第i个牲畜围栏中的动物长大后,每只牛可以卖a[i]元,每只羊可以卖b[i]元,为了防止牛羊之间相互影响,Mike找到了m条规律,每条规律给出一个三元组(i, j, k)表示如果第i个围栏和第j个围栏养的是不同的动物,那么Mike就需要花费k的代价请人帮忙处理牛羊之间的影响。不过同时Mike也发现k条特殊的规则(S, a, b),表示如果S中所有牲畜围栏中都养的是动物a,那么Mike可以获得b的额外收入。现在Mike想知道他该在哪些围栏中饲养什么动物才能使得总收益最大,为了简化问题,你只需要输出最大收益。
输入
第一行三个整数n、m、k,表示一共有n个围栏,m条规律,k条规则。
第二行有n个整数,表示a[i]。
第三行有n个整数,表示b[i]。
接下来m行,每行有三个整数(i, j, k)表示一条规则。
再接下来k行,每行一开始有三个整数t、a和b,表示一条规则(S, a, b),其中S的大小为t,接下来t个整数表示S中的元素(a为0表示全为牛,a为1表示全为羊)。
输出
输出一个整数ans,表示最大收益。
样例输入
4 2 1
1 2 3 1
2 3 1 2
1 2 3
1 3 2
2 0 100 1 2
样例输出
108
题解
经典的网络流最小割建模
建模方法:
S向x连边,容量为a[x];x向T连边,容量为b[x];
如果两个选择不同则要付出代价,那么在它们之间连双向边,容量为代价k;
如果P集合内全部选择S端则获得额外收益,那么建一个新点p代表集合,S向p连边,容量为收益,p向P中每个点连边,容量为$\infty$;全部选择T端同理,每个点连p,p连T。
跑最小割,答案为所有收益之和-最小割。
#include <queue>
#include <cstdio>
#include <cstring>
#define N 10010
#define M 1000010
#define inf 1 << 30
using namespace std;
queue<int> q;
int head[N] , to[M] , val[M] , next[M] , cnt = 1 , s , t , dis[N];
inline void add(int x , int y , int z)
{
to[++cnt] = y , val[cnt] = z , next[cnt] = head[x] , head[x] = cnt;
to[++cnt] = x , val[cnt] = 0 , next[cnt] = head[y] , head[y] = cnt;
}
bool bfs()
{
int x , i;
memset(dis , 0 , sizeof(dis));
while(!q.empty()) q.pop();
dis[s] = 1 , q.push(s);
while(!q.empty())
{
x = q.front() , q.pop();
for(i = head[x] ; i ; i = next[i])
{
if(val[i] && !dis[to[i]])
{
dis[to[i]] = dis[x] + 1;
if(to[i] == t) return 1;
q.push(to[i]);
}
}
}
return 0;
}
int dinic(int x , int low)
{
if(x == t) return low;
int temp = low , i , k;
for(i = head[x] ; i ; i = next[i])
{
if(val[i] && dis[to[i]] == dis[x] + 1)
{
k = dinic(to[i] , min(temp , val[i]));
if(!k) dis[to[i]] = 0;
val[i] -= k , val[i ^ 1] += k;
if(!(temp -= k)) break;
}
}
return low - temp;
}
int main()
{
int n , m , k , i , x , y , z , sum = 0;
scanf("%d%d%d" , &n , &m , &k) , s = 0 , t = n + k + 1;
for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &x) , add(s , i , x) , sum += x;
for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &x) , add(i , t , x) , sum += x;
for(i = 1 ; i <= m ; i ++ ) scanf("%d%d%d" , &x , &y , &z) , add(x , y , z) , add(y , x , z);
for(i = 1 ; i <= k ; i ++ )
{
scanf("%d%d%d" , &x , &y , &z) , sum += z;
if(y)
{
add(i + n , t , z);
while(x -- ) scanf("%d" , &y) , add(y , i + n , inf);
}
else
{
add(s , i + n , z);
while(x -- ) scanf("%d" , &y) , add(i + n , y , inf);
}
}
while(bfs()) sum -= dinic(s , inf);
printf("%d\n" , sum);
return 0;
}
【bzoj4177】Mike的农场 网络流最小割的更多相关文章
- BZOJ_4177_Mike的农场_最小割
BZOJ_4177_Mike的农场_最小割 Description Mike有一个农场,这个农场n个牲畜围栏,现在他想在每个牲畜围栏中养一只动物,每只动物可以是牛或羊,并且每个牲畜围栏中的饲养条件都不 ...
- 【题解】 bzoj3894: 文理分科 (网络流/最小割)
bzoj3894,懒得复制题面,戳我戳我 Solution: 首先这是一个网络流,应该还比较好想,主要就是考虑建图了. 我们来分析下题面,因为一个人要么选文科要么选理科,相当于两条流里面割掉一条(怎么 ...
- 【bzoj3774】最优选择 网络流最小割
题目描述 小N手上有一个N*M的方格图,控制某一个点要付出Aij的代价,然后某个点如果被控制了,或者他周围的所有点(上下左右)都被控制了,那么他就算是被选择了的.一个点如果被选择了,那么可以得到Bij ...
- 【bzoj1143】[CTSC2008]祭祀river Floyd+网络流最小割
题目描述 在遥远的东方,有一个神秘的民族,自称Y族.他们世代居住在水面上,奉龙王为神.每逢重大庆典, Y族都会在水面上举办盛大的祭祀活动.我们可以把Y族居住地水系看成一个由岔口和河道组成的网络.每条河 ...
- 【bzoj1797】[Ahoi2009]Mincut 最小割 网络流最小割+Tarjan
题目描述 给定一张图,对于每一条边询问:(1)是否存在割断该边的s-t最小割 (2)是否所有s-t最小割都割断该边 输入 第一行有4个正整数,依次为N,M,s和t.第2行到第(M+1)行每行3个正 整 ...
- 【bzoj1976】[BeiJing2010组队]能量魔方 Cube 网络流最小割
题目描述 一个n*n*n的立方体,每个位置为0或1.有些位置已经确定,还有一些需要待填入.问最后可以得到的 相邻且填入的数不同的点对 的数目最大. 输入 第一行包含一个数N,表示魔方的大小. 接下来 ...
- 【bzoj3438】小M的作物 网络流最小割
原文地址:http://www.cnblogs.com/GXZlegend/p/6801522.html 题目描述 小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物 ...
- 【bzoj3144】[Hnoi2013]切糕 网络流最小割
题目描述 输入 第一行是三个正整数P,Q,R,表示切糕的长P. 宽Q.高R.第二行有一个非负整数D,表示光滑性要求.接下来是R个P行Q列的矩阵,第z个 矩阵的第x行第y列是v(x,y,z) (1≤x≤ ...
- 【bzoj3894】文理分科 网络流最小割
原文地址:http://www.cnblogs.com/GXZlegend 题目描述 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠结过) 小P所在的班级要进行文理分科.他的班级可以用 ...
随机推荐
- python 多进程,多线程,协程
在我们实际编码中,会遇到一些并行的任务,因为单个任务无法最大限度的使用计算机资源.使用并行任务,可以提高代码效率,最大限度的发挥计算机的性能.python实现并行任务可以有多进程,多线程,协程等方式. ...
- Python的静态方法和类方法
Python中使用@staticmethod这个装饰器让方法变为静态方法 一:定义 @staticmethod: 首先它是一个装饰器,被装饰的方法不需要隐含的参数,对象和对象的实例都可以调用静态方法 ...
- Linux帮助都有哪几种,如何使用?
帮助文件有2类,内置命令和外部命令. 其中内置命令就是shell内核自带的,因为shell当中自己要进行管理,那么就需要一些命令进行管理,不同的shell肯定有不同的shell命令,我们用type命令 ...
- oracle中序列,同义词的创建
序列 序列是用来生成唯一,连续的整数的数据库对象.序列通常用来自动生成主机那或唯一键的值.序列可以按升序排序, 也可以按降序排序.例如,销售流水表中的流水号可以使用序列自动生成. 创建序列语法: cr ...
- kickstart+pxe+tftp+ntp(http)自动化安装平台的搭建
听说过"克隆"吗,对于这个科技术语20年前可能还很陌生,羊可以克隆,通过基因dna序列:机器同样可以克隆通过网络IP! 如下为自动化安装平台: PXE(preboot execut ...
- day1_作业(账户登录检测)
#!/usr/local/bin/python3 # -*- coding:utf-8 -*- f=open('/users/zhangyu/PycharmProjects/s14/day1/Home ...
- 解决cmd 运行python socket怎么终止运行
在cmd里启动python写了一个socket服务端的程序,但是启动之后由于监听连接的是一个死循环 这时想终止运行,发现按ctrl+c,ctrl+z,ctrl+d都不能终止 用ctrl+break解决
- [Codeforces86D]Powerful array(莫队算法)
题意:定义K[x]为元素x在区间[l,r]内出现的次数,那么它的贡献为K[x]*K[x]*x 给定一个序列,以及一些区间询问,求每个区间的贡献 算是莫队算法膜版题,不带修改的 Code #includ ...
- Java设置模式
单例模式 装饰者模式 代理模式
- dfs序线段树
dfs序+线段树,啥?如果在一棵树上,需要你修改一些节点和查询一些节点,如果直接dfs搜的话肯定超时,那用线段树?树结构不是区间啊,怎么用?用dfs序将树结构转化为一个区间,就能用线段树进行维护了. ...