<题目链接>

题目大意:
有一个养猪场,厂长没有钥匙,这个养猪场一共M个猪圈,N个顾客,每个顾客有一些猪圈的钥匙,每个顾客需要一些猪,问你厂长最多能卖多少猪?这里有个条件是,厂长可以在一个顾客买完后,调整没有锁门的猪圈中猪数量,比如,把几个猪圈中的猪全部转到一个猪圈内(这个条件会影响到后期建图),然后再关门,等下一个顾客。

解题分析:

首先根据题意,将这个问题抽象成一个朴素的模型,

因为这样建图,图中最多可能有$2+N+M+N*M (≈1e5)$个节点。在这样的图上跑网络流速度会很慢,我们可以通过合并一些等效的点来达到简化模型的目的。

规律 1.  如果几个结点的流量的来源完全相同,则可以把它们合并成一个。

规律 2.  如果几个结点的流量的去向完全相同,则可以把它们合并成一个。

规律 3.  如果从点 u 到点 v 有一条容量为∞的边,并且点 v 除了点 u 以外没有别的流量来源,则可以把这两个结点合并成一个。

具体简化过程见  >>>

简化后的图为:

因此,最终的建图方案就是:源点到所有第一个打开各个猪圈的人连上一条边,容量为这个猪圈的数量上限,然后,上一个打开这个猪圈的人向下一个打开这个猪圈的人连一条容量为无穷的边,最后,所有人向汇点连一条边,容量为他所能拿的猪数量的上限。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std; typedef long long ll;
const ll INF = 1e18;
const int N = 1e3+; template<typename T>
inline void read(T&x){
x=;int f=;char ch=getchar();
while(ch<''||ch>''){ if(ch=='-')f=-;ch=getchar(); }
while(ch>=''&&ch<=''){ x=x*+ch-'';ch=getchar(); }
x*=f;
}
struct Dinic
{
struct edge{ int from,to;ll cap,flow; };
vector<edge>es;
vector<int>G[N];
bool vis[N];
int dist[N],iter[N];
void init(int n){
for(int i=; i<=n+; i++)G[i].clear();
es.clear();
}
void addedge(int from,int to,ll cap){
es.push_back((edge){from,to,cap,}); //将边存储的边表
es.push_back((edge){to,from,,});
int x=es.size();
G[from].push_back(x-); //G[u][i]记录以u为顶点的第i条边的反边在es中的编号
G[to].push_back(x-);
}
bool BFS(int s,int t){ //bfs将该图划分成分层图
memset(vis,,sizeof(vis));
queue <int> q;
vis[s]=;
dist[s]=;
q.push(s);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=; i<G[u].size(); i++){
edge &e=es[G[u][i]];
if(!vis[e.to]&&e.cap>e.flow){
vis[e.to]=;
dist[e.to]=dist[u]+;
q.push(e.to);
}
}
}
return vis[t];
}
int DFS(int u,int t,ll f){
if(u==t||f==)return f;
int lastflow=,d;
for(int &i=iter[u]; i<G[u].size(); i++){
edge &e=es[G[u][i]];
if(dist[u]+==dist[e.to]&&(d=DFS(e.to,t,min(f,e.cap-e.flow)))>){
e.flow+=d; //正边真实流量-d
es[G[u][i]^].flow-=d; //反边真实流量+d
lastflow+=d; //得到现在搜得的能够流入汇点的流量
f-=d; //找到一条增广路之后,减去这条路的流量,然后继续从这个顶点的其它边开始寻找增广路
if(f==)break;
}
}
return lastflow;
}
int Maxflow(int s,int t){
int flow=;
while(BFS(s,t)){
memset(iter,,sizeof(iter));
int d=;
while(d=DFS(s,t,INF))flow+=d;
}
return flow;
}
}dinic; int n,m,st,ed,last[N],pig[N]; //last记录上一个打开对应猪圈的人
int main(){
read(m);read(n);st=;ed=n+;
for(int i=;i<=m;i++) read(pig[i]);
for(int i=;i<=n;i++){
int k;read(k);
while(k--){
int x;read(x);
if(!last[x]) dinic.addedge(st,i,pig[x]),last[x]=i; //如果是第一个打开该猪圈的人,就直接从源点向他连一条边
else dinic.addedge(last[x],i,INF),last[x]=i; //如果这个猪圈已经被打开过了,就从上一个打开的人向他连一条边
}
ll cal;read(cal);
dinic.addedge(i,ed,cal); //每个人向汇点连一条边,容量为他们能够拿的猪的上限
}
cout<<dinic.Maxflow(st,ed)<<endl;
}

POJ 1149 PIGS 【最大流】的更多相关文章

  1. POJ 1149 - PIGS - [最大流构图]

    Time Limit: 1000MS Memory Limit: 10000K Description Mirko works on a pig farm that consists of M loc ...

  2. poj 1149 pigs ---- 最大流

    题意以及分析:http://ycool.com/post/zhhrrm6#rule3 主要是建图,简化图,然后在套最大流的模板. #include <iostream> #include& ...

  3. poj 1149 pigs(最大流)

    题目大意:迈克在农场工作,农场有 m 个猪舍,每个猪舍有若干只猪,但是迈克不能打开任何一间猪舍.有 n 个顾客前来购买,每个顾客有最大的购买数量,每个顾客可以购买某些猪舍的猪,且顾客可以打开这些猪舍, ...

  4. [poj] 1149 PIGS || 最大流经典题目

    原题 题目大意 给你m个猪圈以及每个猪圈里原来有多少头猪,先后给你n个人,每个人能打开一些猪圈并且他们最多想买Ki头猪,在每一个人买完后能将打开的猪圈中的猪顺意分配在这次打开猪圈里,在下一个人来之前 ...

  5. POJ 1149 PIGS(Dinic最大流)

    PIGS Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20738   Accepted: 9481 Description ...

  6. poj 1149 Pigs 网络流-最大流 建图的题目(明天更新)-已更新

    题目大意:是有M个猪圈,N个顾客,顾客要买猪,神奇的是顾客有一些猪圈的钥匙而主人MIRKO却没有钥匙,多么神奇?顾客可以在打开的猪圈购买任意数量的猪,只要猪圈里有足够数量的猪.而且当顾客打开猪圈后mi ...

  7. 网络流(最大流):POJ 1149 PIGS

    PIGS Time Limit: 1000ms Memory Limit: 10000KB This problem will be judged on PKU. 64-bit integer(整数) ...

  8. POJ 1149 PIGS(最大流)

    Description Mirko works on a pig farm that consists of M locked pig-houses and Mirko can't unlock an ...

  9. poj 1149 PIGS【最大流经典建图】

    PIGS Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 18727   Accepted: 8508 Description ...

  10. poj 1149 PIGS(最大流经典构图)

    题目描述:迈克在一个养猪场工作,养猪场里有M 个猪圈,每个猪圈都上了锁.由于迈克没有钥匙,所以他不能打开任何一个猪圈.要买猪的顾客一个接一个来到养猪场,每个顾客有一些猪圈的钥匙,而且他们要买一定数量的 ...

随机推荐

  1. git 操作命令详解

    git 什么是git 开源的分布式版本控制系统, 用于高效的管理大小项目和文件 代码管理工具 防止代码丢失, 做备份 代码版本管控, 设置节点, 多版本切换 建立分支各自开发, 互不影响, 方便合并 ...

  2. pandas常用函数之diff

    diff函数是用来将数据进行某种移动之后与原数据进行比较得出的差异数据,举个例子,现在有一个DataFrame类型的数据df,如下: index value1 A 0 B 1 C 2 D 3 如果执行 ...

  3. 海亮OI学习游记

    这只是一篇纯洁的游记,这里将要记录我在海亮十天集训的生活与被虐的历史QWQ...... Day1(2.10)刚来到海亮,嗯,这的环境真的不错. 来到机房,woc这机房的配置好高啊...这里都能打守望屁 ...

  4. JS常用基础知识

    前言:在js中dom和bom是我们操作的基本,在最初接触时候我也懵,但是后来慢慢发现其实bom就是操作浏览器,而dom就是操作文本框节点.

  5. Dubbo学习笔记8:Dubbo的线程模型与线程池策略

    Dubbo默认的底层网络通讯使用的是Netty,服务提供方NettyServer使用两级线程池,其中 EventLoopGroup(boss) 主要用来接受客户端的链接请求,并把接受的请求分发给 Ev ...

  6. 老是上不了 google scholar...

    这段时间老是上不了 google scholar... 下载了最新的 host 也不行. 难道真是电脑有问题了? 网络有时也老是掉... 也好. 多休息休息. 人生难得几回清闲. 马上就要开学咯. 课 ...

  7. EffectiveC++ 第1章 让自己习惯C++

    我根据自己的理解,对原文的精华部分进行了提炼,并在一些难以理解的地方加上了自己的"可能比较准确"的「翻译」. Chapter 1 让自己习惯C++ 条款 1 :视 C++为一个语言 ...

  8. burp Suite 模块Authz 使用方法

    这个模块是朋友告诉我的,然后进行了研究使用方法. 以下为个人理解,如有错误感谢各位纠正. 0x00 安装Authz Extender > BApp Store > Authz > i ...

  9. TensorFlow资源整理

    什么是TensorFlow? TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库.节点(Nodes)在图中表示数学操作,图中的线(edges)则表示 ...

  10. 出现Failed to get convolution algorithm的解决方法

    当运行卷积神经时出现了问题:Failed to get convolution algorithm. This is probably because cuDNN failed to initiali ...