【题解】小M的作物
\(\text{Solution:}\)
这题要求最大收获,可以转化为所有可能的收益减去最小割。
单个点很好连边 \((S\to pos\to T),\) 问题在于如何处理组合的点。
观察到,一个组合要不然全部都划分到某一个集合,要不然不做贡献。注意到组合里面的点是不能拆开的。
所以我们建立一个组合虚点,它连接所有组合内的点,边权是 \(\infty.\) 这样就一定可以避免把它们划分到不同集合中。
那么,我们可以考虑如下建模模型:
\(\text{S}\to \text{compose} \to \text{everypoints in this group} \to \text{compose endpoint} \to \text{T}.\)
本题我们可以把 \(A\) 看作 \(S,T\) 同理。
于是这个题再套上我们最熟悉的\(\text{Dinic}\)模板就过了。
最后来分析一下这个图的规模:
首先,所有点都应该有一个对应点,再加上每一个集合的开始点和结束点,共\(n+m+m\)个。最大是\(3000.\)
对于边:每个点对源点和汇点都会连边,这里是\(n+n.\)每一个组合,其边数是组合中的点数的两倍,共约为\(n+n+2mk.\)最大数据是\(2*10^6+2000.\)
根据\(Dinic\)的复杂度\(O(n^2 m)\)这个数量级显然会炸,但是出题人毕竟一定会让\(Dinic\)过,以及\(Dinic\)复杂度跑不满的原因,这个算法是可以过的。
#include<bits/stdc++.h>
using namespace std;
const int inf=(1<<30);
const int MAXN=2e6+10;
int tot=1,head[MAXN];
int dep[MAXN],cur[MAXN];
int n,a[MAXN],b[MAXN],m;
int Ans,c1[MAXN],c2[MAXN],S,T;
vector<int>v[MAXN];
struct E{int nxt,to,flow;}e[MAXN];
inline void add(int x,int y,int w){
e[++tot].to=y;e[tot].nxt=head[x];
e[tot].flow=w;head[x]=tot;
e[++tot].to=x;e[tot].nxt=head[y];
e[tot].flow=0;head[y]=tot;
}
bool bfs(int s,int t){
memset(dep,0,sizeof dep);
cur[s]=head[s];dep[s]=1;
queue<int>q;q.push(s);
while(!q.empty()){
s=q.front();
q.pop();
for(int i=head[s];i;i=e[i].nxt){
int j=e[i].to;
if(!dep[j]&&e[i].flow){
cur[j]=head[j];
dep[j]=dep[s]+1;
if(j==t)return true;
q.push(j);
}
}
}
return false;
}
int dfs(int s,int flow,int t){
if(flow<=0||s==t)return flow;
int rest=flow;
for(int i=cur[s];i;i=e[i].nxt){
int j=e[i].to;
if(dep[j]==dep[s]+1&&e[i].flow){
int tmp=dfs(j,min(rest,e[i].flow),t);
if(tmp<=0)dep[j]=0;
rest-=tmp;e[i].flow-=tmp;e[i^1].flow+=tmp;
if(rest<=0)break;
}
}
return flow-rest;
}
int dinic(int s,int t){
int ans=0;
for(;bfs(s,t);)ans+=dfs(s,inf,t);
return ans;
}
void Deal(){
S=0,T=n+m+m+1;
for(int i=1;i<=n;++i)add(S,i,a[i]),add(i,T,b[i]);
for(int i=1;i<=m;++i){
int pos=i+n;add(S,pos,c1[i]);
int posend=i+n+m;
for(int j=0;j<(int)v[i].size();++j)
add(pos,v[i][j],inf),add(v[i][j],posend,inf);
add(posend,T,c2[i]);
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%d",a+i),Ans+=a[i];
for(int i=1;i<=n;++i)scanf("%d",b+i),Ans+=b[i];
scanf("%d",&m);
for(int i=1,k;i<=m;++i){
scanf("%d",&k);
scanf("%d%d",&c1[i],&c2[i]);
Ans+=c1[i];Ans+=c2[i];
for(int j=1,x;j<=k;++j){
scanf("%d",&x);
v[i].push_back(x);
}
}
Deal();
printf("%d\n",Ans-dinic(S,T));
return 0;
}
【题解】小M的作物的更多相关文章
- 善意的投票&小M的作物 题解
善意的投票: 因为只有\(2\)种意愿,不妨让想睡午觉的和源点连边,让不想睡午觉的和汇点连边.对于每一对好朋友,在他们之间连边.那么只要源点和汇点还联通,就存在一对好友是冲突的,我们现在要做的就是删去 ...
- BZOJ 3438: 小M的作物( 最小割 )
orz出题人云神... 放上官方题解... 转成最小割然后建图跑最大流就行了... ---------------------------------------------------------- ...
- BZOJ 3438 小M的作物 & BZOJ 1877 [SDOI2009]晨跑
我由衷地为我的朋友高兴.哈哈,yian,当你nick name破百上千时,再打“蒟蒻”就会被打的. 好的,说正事吧.请注意,这还是题解.但我发现,网络流实在是太套路了(怪不得这两年几乎销声匿迹).我们 ...
- 【BZOJ3438】小M的作物 最小割
[BZOJ3438]小M的作物 Description 小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子 有1个(就是可以种一棵作物)(用1. ...
- luogu P1361 小M的作物
题目链接 luogu P1361 小M的作物 题解 源汇点为A,B 向种子连边,容量为价值,每个种子能与A或B联通,考虑最小割 用建边的总流量减去最小割就是答案 相同利益的时候新建节点,由额外利益构成 ...
- 「BZOJ3438」小M的作物(最小割
3438: 小M的作物 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1891 Solved: 801[Submit][Status][Discus ...
- bzoj3438: 小M的作物(那年花开最小割)
3438: 小M的作物 题目:传送门 题解: 最小割标准水题(做了几天的最小割之后表示是真的水) 为什么水:博主已经做过两道基本一样的题目了... 详情参考:bzoj3894 代码: #include ...
- 【BZOJ-3438】小M的作物 最小割 + 最大权闭合图
3438: 小M的作物 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 825 Solved: 368[Submit][Status][Discuss ...
- P1361 小M的作物
P1361 小M的作物 题目描述 小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子有1个(就是可以种一棵作物)(用1...n编号). 现在,第 ...
- BZOJ_3438_小M的作物_最小割
BZOJ_3438_小M的作物_最小割 Description 小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子 有1个(就是可以种一棵作物) ...
随机推荐
- ios 常见性能优化
1. 用ARC管理内存 2. 在正确的地方使用reuseIdentifier 3. 尽可能使Views透明 4. 避免庞大的XIB 5. 不要block主线程 6. 在Image Views中调整图片 ...
- [BUUOJ记录] [SUCTF 2019]CheckIn
比较经典的一道文件上传题,考察.user.ini控制解析图片方式 打开题目给出了上传功能,源代码里也没有任何提示,看来需要先测试一下过滤 前后依次提交了php,php5,php7,phtml拓展名的文 ...
- Activiti7 流程部署
首先先绘制一个流程图 创建bpmn文件 然后绘制好节点 然后修改节点信息 指定负责人 点击背景,修改ID和名称 保存 然后重命名成xml 使用diagram打开 导出png 然后包xml改回bpmn ...
- SpringBoot—整合log4j2入门和log4j2.xml配置详解
关注微信公众号:CodingTechWork,一起学习进步. 引言 对于一个线上程序或者服务而言,重要的是要有日志输出,这样才能方便运维.而日志的输出需要有一定的规划,如日志命名.日志大小,日志分 ...
- Agumaster 增加股票表台账页面
- Java的String.matches不区分大小写正则表达式匹配示例
需求:输入的cmd符合create,listall,delete三种形式,不用区分大小写 写成函数: public static boolean isAllowed3Cmd(String cmd) { ...
- Java并发编程之闭锁与栅栏
一.前言 闭锁与栅栏是在多线程编程中的概念,因为在多线程中,我们不能控制线程的执行状态,所以给线程加锁,让其按照我们的想法有秩序的执行. 闭锁 CountDownLatch,实例化时需要传入一个int ...
- 教务管理系统(node+express+mysql)
模块拆分 现在将教务系统拆分成九个模块: 教务系统教师业务:师资管理.教学计划管理.排课管理 教务系统学生业务:考试管理.毕业生管理.学生综合测评 信息查询:自习室查询.课程表查询 考试系统:实现学生 ...
- python中eval()
eval()执行简单的python代码(个人感觉像是执行表达式)
- C#调用Power Shell 管理Office365 执行脚本时遇到的问题
Power Shell管理Office参考http://www.mamicode.com/info-detail-494553.html C#调用Power Shell 参考 https://www. ...