BZOJ3438 小M的作物(最小割)
题目
Source
http://www.lydsy.com/JudgeOnline/problem.php?id=3438
Description
小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子
有1个(就是可以种一棵作物)(用1...n编号),现在,第i种作物种植在A中种植可以获得ai的收益,在B中种植
可以获得bi的收益,而且,现在还有这么一种神奇的现象,就是某些作物共同种在一块耕地中可以获得额外的收益
,小M找到了规则中共有m种作物组合,第i个组合中的作物共同种在A中可以获得c1i的额外收益,共同总在B中可以
获得c2i的额外收益,所以,小M很快的算出了种植的最大收益,但是他想要考考你,你能回答他这个问题么?
Input
第一行包括一个整数n
第二行包括n个整数,表示ai第三行包括n个整数,表示bi第四行包括一个整数m接下来m行,
对于接下来的第i行:第一个整数ki,表示第i个作物组合中共有ki种作物,
接下来两个整数c1i,c2i,接下来ki个整数,表示该组合中的作物编号。输出格式
Output
只有一行,包括一个整数,表示最大收益
Sample Input
3
4 2 1
2 3 2
1
2 3 2 1 2
Sample Output
11
样例解释A耕地种1,2,B耕地种3,收益4+2+3+2=11。
1<=k< n<= 1000,0 < m < = 1000 保证所有数据及结果不超过2*10^9。
分析
各个点要分到两个集合中使价值最大化,考虑最小割。最小割的意义是最少的损失。如此建图:
- 把各种子看作点,源点向各点i连容量ai的边,各点i向汇点连容量bi的边。
- 也把组合看作点,并拆成两点x,x',源点向x连c1i的边,x'向汇点连c2i的边。
- 对于组合x和种子i之间的关系,x向i建容量INF的边,i向x'连容量INF的边。
这样答案就是Σai+Σbi+Σc1i+Σc2i-最小割,画画图就知道了。。
不过其实,一开始我想错了,我建的图是组合没有拆点的图,这样相当于是对于任何一个组合必须选或者不选的结果,事实上可以两个都不选。。比如这个数据就错了:
2
1 100
100 1
1
2 1 1 1 2
代码
- #include<cstdio>
- #include<cstring>
- #include<vector>
- #include<queue>
- #include<algorithm>
- using namespace std;
- #define INF (1<<30)
- #define MAXN 3333
- #define MAXM 2222*2222*2
- struct Edge{
- int v,cap,flow,next;
- }edge[MAXM];
- int vs,vt,NE,NV;
- int head[MAXN];
- void addEdge(int u,int v,int cap){
- edge[NE].v=v; edge[NE].cap=cap; edge[NE].flow=0;
- edge[NE].next=head[u]; head[u]=NE++;
- edge[NE].v=u; edge[NE].cap=0; edge[NE].flow=0;
- edge[NE].next=head[v]; head[v]=NE++;
- }
- int level[MAXN];
- int gap[MAXN];
- void bfs(){
- memset(level,-1,sizeof(level));
- memset(gap,0,sizeof(gap));
- level[vt]=0;
- gap[level[vt]]++;
- queue<int> que;
- que.push(vt);
- while(!que.empty()){
- int u=que.front(); que.pop();
- for(int i=head[u]; i!=-1; i=edge[i].next){
- int v=edge[i].v;
- if(level[v]!=-1) continue;
- level[v]=level[u]+1;
- gap[level[v]]++;
- que.push(v);
- }
- }
- }
- int pre[MAXN];
- int cur[MAXN];
- int ISAP(){
- bfs();
- memset(pre,-1,sizeof(pre));
- memcpy(cur,head,sizeof(head));
- int u=pre[vs]=vs,flow=0,aug=INF;
- gap[0]=NV;
- while(level[vs]<NV){
- bool flag=false;
- for(int &i=cur[u]; i!=-1; i=edge[i].next){
- int v=edge[i].v;
- if(edge[i].cap!=edge[i].flow && level[u]==level[v]+1){
- flag=true;
- pre[v]=u;
- u=v;
- //aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap));
- aug=min(aug,edge[i].cap-edge[i].flow);
- if(v==vt){
- flow+=aug;
- for(u=pre[v]; v!=vs; v=u,u=pre[u]){
- edge[cur[u]].flow+=aug;
- edge[cur[u]^1].flow-=aug;
- }
- //aug=-1;
- aug=INF;
- }
- break;
- }
- }
- if(flag) continue;
- int minlevel=NV;
- for(int i=head[u]; i!=-1; i=edge[i].next){
- int v=edge[i].v;
- if(edge[i].cap!=edge[i].flow && level[v]<minlevel){
- minlevel=level[v];
- cur[u]=i;
- }
- }
- if(--gap[level[u]]==0) break;
- level[u]=minlevel+1;
- gap[level[u]]++;
- u=pre[u];
- }
- return flow;
- }
- int a[1111],b[1111];
- int main(){
- int n,m,tot=0;
- scanf("%d",&n);
- for(int i=1; i<=n; ++i){
- scanf("%d",a+i);
- tot+=a[i];
- }
- for(int i=1; i<=n; ++i){
- scanf("%d",b+i);
- tot+=b[i];
- }
- scanf("%d",&m);
- vs=0; vt=n+m+m+1; NV=vt+1; NE=0;
- memset(head,-1,sizeof(head));
- for(int i=1; i<=n; ++i){
- addEdge(vs,i,a[i]);
- addEdge(i,vt,b[i]);
- }
- int k,x,y;
- for(int i=1; i<=m; ++i){
- scanf("%d",&k);
- scanf("%d%d",&x,&y);
- addEdge(vs,i+n,x);
- addEdge(i+n+m,vt,y);
- tot+=x; tot+=y;
- while(k--){
- scanf("%d",&x);
- addEdge(i+n,x,INF);
- addEdge(x,i+n+m,INF);
- }
- }
- printf("%d",tot-ISAP());
- return 0;
- }
BZOJ3438 小M的作物(最小割)的更多相关文章
- BZOJ3438小M的作物——最小割
题目描述 小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子 有1个(就是可以种一棵作物)(用1...n编号),现在,第i种作物种植在A中种植可 ...
- 【BZOJ3438】小M的作物 最小割
[BZOJ3438]小M的作物 Description 小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子 有1个(就是可以种一棵作物)(用1. ...
- 【BZOJ-3438】小M的作物 最小割 + 最大权闭合图
3438: 小M的作物 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 825 Solved: 368[Submit][Status][Discuss ...
- BZOJ 3438: 小M的作物( 最小割 )
orz出题人云神... 放上官方题解... 转成最小割然后建图跑最大流就行了... ---------------------------------------------------------- ...
- 3438: 小M的作物[最小割]
3438: 小M的作物 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1073 Solved: 465[Submit][Status][Discus ...
- P1361 小M的作物 最小割理解
如果没有组合效益的存在 我们直接每个点两部分的最大值即可 换成网络流模型来看 即把S点看作是A田 把T点看作是B田 每种作物看作一个点 分别连边(S,i,A[i]) (i,T,B[i]) 最后图中所有 ...
- 洛谷 - P1361 - 小M的作物 - 最小割 - 最大权闭合子图
第一次做最小割,不是很理解. https://www.luogu.org/problemnew/show/P1361 要把东西分进两类里,好像可以应用最小割的模板,其中一类A作为源点,另一类B作为汇点 ...
- [P1361] 小M的作物 - 最小割
没想到今天早上的第一题网络流就血了这么多发 从经典的二选一问题上魔改 仍然考虑最小割 #include <bits/stdc++.h> using namespace std; #defi ...
- 小M的作物 最小割最大流
题目描述 小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子有1个(就是可以种一棵作物)(用1...n编号). 现在,第i种作物种植在A中种植可 ...
随机推荐
- php php-5.6.4.tar.bz2 apache 兼容问题 child pid 27858 exit signal Segmentation fault
环境 [root envirotar]# uname -a Linux i2..el6.x86_64 # SMP Thu Jul :: UTC x86_64 x86_64 x86_64 GNU/Lin ...
- 释放修改OS X 10.11系统文件权限【转】
序言:有时要替换相关的(系统目录下的)文件以完成软件的破解,但在 OS X 10.11 系统图形界面下,Root(系统超级用户)已‘转变’为 Administrator(管理员用户),选择系统文件夹( ...
- EKF的理解
若已知参考点(landmarks)的坐标,则状态向量中不必含有xL, 从而实现的仅为机器人在已知环境中的定位,求解大大减少(状态向量维度仅为运动状态).若想实现完整SLAM,必须将xL加入状态向量中. ...
- jquery easyui tree动态加载子节点
1.前端tree绑定时,使用onBeforeExpand事件:当节点展开时触发加载子节点,自动会向服务端发送请求:url为绑定url,参数为当前节点id this.tree = { method: ' ...
- VMware中解决ubuntu不能连接网络问题。(亲测有效)
1.保证自己的电脑能正常连接网络 2.打开关于VMware的所有服务(一般情况服务设置的是手动启动,需要自己打开)如图: 3.对VMware虚拟机进行网络设置:右击ubuntn选择设置 4.选择网络适 ...
- 打不死的redis集群
导读 最近遇到部分系统因为redis服务挂掉,导致部分服务不可用.所以希望搭建一个redis集群镜像,把原先散落各处的redis服务器统一管理起来,并且保障高可用和故障自动迁移. 最近遇到部分系统因为 ...
- Life Is A Funny Proposition After All
你们有没有坐下思考,感到疑惑 ,静静思考,我们为什么在这里 ,生活为什么如此这般 这个问题让无数聪明人喝酒买醉,这是最最奇怪的事情,他们都想弄清楚,科学家们可以展示上千种不同的理论,但从未证明这是为什 ...
- Mac挂载NTFS移动硬盘读取VMware虚拟机文件
一.Mac 挂载NTFS移动硬盘进行读写操作 (Read-only file system) 注意如下图所示先卸载,然后按照下图的命令进行挂载.然后cd /opt/003_vm/ &&am ...
- Unity3D 解决用Unity导出的Android工程在6.0及以上设备会弹出一串权限对话框的问题
解决用Unity导出的Android工程在6.0及以上设备会弹出一串权限对话框的问题 <meta-data android:name="unityplayer.SkipPermissi ...
- 鼠标划过用户名时在鼠标右下角显示div展示用户资料
最近做一个网站论坛,为了方便会员之间相互了解,又不想再做一个页面展示用户资料,就想到了鼠标划过用户名时在鼠标右下角显示div展示用户资料这个效果, 这里要注意的该方法不是给每个用户名的旁边都绑定一个d ...