Sell Pigs 题解
题目大意
有 \(n\) 个顾客前来买猪,共有 \(m\) 个猪圈,每个顾客携带着某一些猪圈的钥匙,需要买一定数量的猪。在顾客买完后,我们可以将打开的猪圈中的猪随意移动,移动完毕后所有的猪圈将关闭,直到下一个顾客到来时才能打开其拥有钥匙对应的猪圈。求最多能卖出多少猪。
思路分析
我们注意到顾客是有时间顺序的。因此,我们首先想到可以建立一张分层图,每个点 \((a,b)\) 表示在第 \(a\) 个顾客到来时的第 \(b\) 个猪圈, 那么边的设置就很自然:
- 建立虚拟源点和汇点,源点向每个 \((1,x)\) 点连边,边权为初始的数量。
- 对于每一层再建一个点,将该层所有被打开的点向它连边,同时它向下一层对于的点连边,边权均为 \(+\infty\),再将其向汇点连边,边权为 \(+\infty\)。

然后跑最大流就可以了。
但是,这样的空间复杂度是 \(O(nm)\) 的,时间复杂度更是高达 \(O(n^3m^3)\),是比较劣的,如何优化呢?
既然顾客有时间顺序,那么我们不妨从顾客下手,只建立 \(n\) 个代表顾客的点,那么如何连边呢?
- 建立虚拟源点,汇点。
- 每个点向汇点连边,边权是这个顾客对猪的需求量。
- 记录每个猪圈最近一次是被谁打开的,如果是第一次打开,将从源点向这个顾客连的边的边权增加这个猪圈的猪的数量。(如果没有这条边就建立这条边)
- 如果不是第一次打开,将上一次打开这个猪圈的顾客向这个顾客连一条边权是 \(+\infty\) 的边。

然后跑最大流就可以了。
空间复杂度 \(O(n)\),时间复杂度 \(O(n^3)\)。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=100100;
#define inf 0x3f3f3f3f
int to[N],nxt[N],head[N],w[N];
int idx=1,n,m,S,T,in1,in2;
int d[N],cur[N];queue <int> q;
int a[N],vis[N];//a 是猪圈中猪的数量,vis 保存上一次打开的人
void add(int u,int v,int c){
idx++;to[idx]=v;nxt[idx]=head[u];head[u]=idx;w[idx]=c;
idx++;to[idx]=u;nxt[idx]=head[v];head[v]=idx;w[idx]=0;
}
//dinic模板默写
bool bfs(){
memset(d,-1,sizeof d);d[S]=0;
while(!q.empty()) q.pop();
cur[S]=head[S];q.push(S);
while(!q.empty()){
int now=q.front();q.pop();
for(int i=head[now];i;i=nxt[i]){
int v=to[i];
if(~d[v]||!w[i]) continue;
d[v]=d[now]+1;cur[v]=head[v];
if(v==T) return 1;q.push(v);
}
}
return 0;
}
int dfs(int s,int lim){
if(s==T) return lim;
int flow=0;
for(int i=cur[s];i&&flow<lim;i=nxt[i]){
int v=to[i];cur[s]=i;
if(d[v]!=d[s]+1||!w[i]) continue;
int t=dfs(v,min(w[i],lim-flow));
if(!t) d[v]=-1;
w[i]-=t;w[i^1]+=t;flow+=t;
}
return flow;
}
int dinic(){
int ans=0,flow=0;
while(bfs()) while(flow=dfs(S,inf)) ans+=flow;
return ans;
}
//------
int main(){
scanf("%d%d",&m,&n);
S=0;T=N-2;//虚拟源汇点
for(int i=1;i<=m;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++){
scanf("%d",&in1);
int sum1=0;
for(int j=1;j<=in1;j++){
scanf("%d",&in2);
if(!vis[in2]){sum1+=a[in2];}//增加边权
else add(vis[in2],i,inf);//上一个人向这个人连边
vis[in2]=i;//更新这个猪圈
}
if(sum1) add(S,i,sum1);
scanf("%d",&in1);
add(i,T,in1);//向汇点连边
}
cout<<dinic()<<'\n';
return 0;
}
Sell Pigs 题解的更多相关文章
- POJ1149:PIGS——题解
http://poj.org/problem?id=1149 题目大意: Mirko有M个猪圈和N个客户,猪圈里有特定数量的猪,每个客户按照顺序来买猪,他们只能打开他们能打开的猪圈,然后取走一些猪(上 ...
- [Leetcode Week6]Best Time to Buy and Sell Stock
Best Time to Buy and Sell Stock 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/best-time-to-buy-and ...
- [LeetCode 题解]:Best Time to Buy and Sell Stock
前言 [LeetCode 题解]系列传送门: http://www.cnblogs.com/double-win/category/573499.html 1.题目描述 Say you ha ...
- Lintcode393 Best Time to Buy and Sell Stock IV solution 题解
[题目描述] Say you have an array for which the i th element is the price of a given stock on day i. Desi ...
- [LeetCode]题解(python):123-Best Time to Buy and Sell Stock III
题目来源: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/ 题意分析: 和上题类似,array[i]代表第i天物品 ...
- [LeetCode]题解(python):122-Best Time to Buy and Sell Stock II
题目来源: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/ 题意分析: 和上题类似,给定array,代表第i天物品i ...
- [LeetCode]题解(python):121-Best Time to Buy and Sell Stock
题目来源: https://leetcode.com/problems/best-time-to-buy-and-sell-stock/ 题意分析: 给定一个数组,代表array[i] 代表第i天的价 ...
- 题解 POJ1149 Pigs
先翻译一下吧(题面可以在原OJ上找) Mirko在一个由M个锁着的猪舍组成的养猪场工作,Mirko无法解锁任何猪舍,因为他没有钥匙.客户纷纷来到农场.他们每个人都有一些猪舍的钥匙,并想购买一定数量的猪 ...
- CF116B Little Pigs and Wolves 题解
Content 有一张 \(n\times m\) 的地图,其中,\(\texttt{P}\) 代表小猪,\(\texttt{W}\) 代表狼.如果狼的上下左右有一头以上的小猪,那么它会吃掉其中相邻的 ...
- [题解] Codeforces 1548 C The Three Little Pigs 组合数学,生成函数
题目 首先令\(x=i\)时的答案为\(f_i\) ,令\(f_i\)对应的普通生成函数为\(F(x)\). 很容易发现\(F(x)=\sum_{i=0}^n (1+x)^{3i}\),sigma是在 ...
随机推荐
- matlab转C++——C++中的矩阵运算和矩阵型函数
最近接到一个委托,把matlab代码转译为c++语言,看看能不能提高运行效率. matlab虽然本身具有将程序转化为C++的app库,但是对代码格式有严格的要求: 变量使用之前需要对变量类型和空间大小 ...
- docker 安装redis 6.0.8哨兵集群(一主两从三哨兵)
准备三台主机并且安装了docker 192.168.31.132 192.168.31.134 192.168.31.144 linux 版redis6.0.8 下载 下载地址:https://dow ...
- 初识常量变量、字符串、ASCII编码表、转义字符表
一.常量.变量 1.枚举常量(enum) 枚举常量不能更改,枚举常量所创造出的变量可以更改 正确 错误 2.常变量 3.#define定义的标示变量 二.数组 "abc"--'a' ...
- 基于SM4和LSB算法实现图片数字水印加密软件(密码赛)
一.前言 密码赛和星火杯时做的小项目,密码赛的时候是个半成品,没有过初赛,星火杯之前完善了 设计思路 最开始是想做一个图片水印用作对图片来源的不可否认性做保护,又考虑保护数据完整性,因此选中了易损水印 ...
- MySQL——GROUP BY详解与优化
在 MySQL 中,GROUP BY用于将具有指定列中相同值的行分组在一起.这是在处理大量数据时非常有用的功能,允许对数据进行分类和聚合. 基本使用 语法 以下是GROUP BY子句的基本语法: &q ...
- 交换机:ToR、EoR
参考链接: 交换机:ToR.EoR ToR:(Top of Rack)接入方式就是在服务器机柜的最上面安装接入交换机. EoR:(End of Row)接入交换机集中安装在一列机柜端部的机柜内,通过水 ...
- 代码随想录算法训练营第二天| LeetCode 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II
977.有序数组的平方 题目链接:https://leetcode.cn/problems/squares-of-a-sorted-array/ 文章讲解:https://programmercarl ...
- java文件共享实现方案
写在前面,由于项目要求负载,又不想大动干戈采用比较贵的设备和高大上的框架,经过一番研究,想使用文件共享方式实现文件的跨服务器访问.本方案采用了jcifs和smbj框架,若想用,请自行查找资源.此为初步 ...
- Cobalt Strike使用教程二
0x00 前言 继前一章介绍了Cobalt Strike的基本用法,本章接着介绍如何攻击.提权.维权等. 0x01 与Metasploit联动 Cobalt Strike → Metasploit m ...
- PB从入坑到放弃(六)动态SQL应用
写在前面 动态 SQL 语句是部分或者整个 SQL 语句在运行时才能确定,可以更好的与用户进行交互,大大提高了SQL的灵活性 一.执行SQL语句 1.1 执行无入参SQL ① 语法 EXECUTE I ...