3438: 小M的作物

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 729  Solved: 328
[Submit][Status][Discuss]
Description

背景

小M还是个特么喜欢玩MC的孩纸。。。

描述

小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

只有一行,包括一个整数,表示最大收益

解四个方程。。

为了简洁我们画出来两个来解方程推理一下。

S->a: Aa

S->b: Ab

a->T: Ba

b->T: Bb

S->x: a和其他相关格子收益

x->T: 同上

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define maxn 1000010
using namespace std;int n, m;const int inf = 0x7fffffff;struct Edge{int to, next, w;
}edge[maxn << 2];int h[10010], cnt = 1;void add(int u, int v, int w){cnt ++;edge[cnt].to = v;edge[cnt].next = h[u];edge[cnt].w = w;h[u] = cnt;swap(u, v), w = 0;cnt ++;edge[cnt].to = v;edge[cnt].next = h[u];edge[cnt].w = w;h[u] = cnt;
}queue<int>Q;int d[3010], S, T, a[3010], b[3010], tmp[3010];bool BFS(){memset(d, -1, sizeof d);Q.push(S);d[S] = 0;while(!Q.empty()){int u = Q.front();Q.pop();for(int i = h[u]; i; i = edge[i].next){if(!edge[i].w)continue;int v = edge[i].to;if(d[v] == -1){d[v] = d[u] + 1;Q.push(v);}}}return d[T] != -1;
}int DFS(int x, int a){if(x == T || a == 0)return a;int used = 0, f;for(int i = h[x]; i; i = edge[i].next){int v = edge[i].to;if(d[v] == d[x] + 1){f = DFS(v, min(a - used, edge[i].w));edge[i].w -= f;edge[i ^ 1].w += f;used += f;if(used == a)return used;}}if(used == 0)d[x] = -1;return used;
}int Dinic(){int ans = 0;while(BFS())ans += DFS(S, inf);return ans;
}int main(){int total = 0;scanf("%d", &n);S = 0, T = 3001;for(int i = 1; i <= n; i ++){scanf("%d", &a[i]);add(S, i, a[i]);total += a[i];}for(int i = 1; i <= n; i ++){scanf("%d", &b[i]);add(i, T, b[i]);total += b[i];}scanf("%d", &m);int k, size = n, c1 = 0, c2 = 0;while(m --){scanf("%d%d%d", &k, &c1, &c2);for(int i = 1; i <= k; i ++)scanf("%d", &tmp[i]);size ++;add(S, size, c1);for(int i = 1; i <= k; i ++)add(size, tmp[i], inf);total += c1;size ++;add(size, T, c2);for(int i = 1; i <= k; i ++)add(tmp[i], size, inf);total += c2;}printf("%d\n", total - Dinic());return 0;
}

3894: 文理分科

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 339  Solved: 213
[Submit][Status][Discuss]
Description

文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠
结过)
 小P所在的班级要进行文理分科。他的班级可以用一个n*m的矩阵进行
描述,每个格子代表一个同学的座位。每位同学必须从文科和理科中选择
一科。同学们在选择科目的时候会获得一个满意值。满意值按如下的方式
得到:
1.如果第i行第秒J的同学选择了文科,则他将获得art[i][j]的满意值,如
  果选择理科,将得到science[i][j]的满意值。
2.如果第i行第J列的同学选择了文科,并且他相邻(两个格子相邻当且
  仅当它们拥有一条相同的边)的同学全部选择了文科,则他会更开
  心,所以会增加same_art[i][j]的满意值。
3.如果第i行第j列的同学选择了理科,并且他相邻的同学全部选择了理
  科,则增加same_science[i]j[]的满意值。
  小P想知道,大家应该如何选择,才能使所有人的满意值之和最大。请
告诉他这个最大值。
Input

第一行为两个正整数:n,m
接下来n术m个整数,表示art[i][j];
接下来n术m个整数.表示science[i][j];
接下来n术m个整数,表示same_art[i][j];
Output

输出为一个整数,表示最大的满意值之和

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define maxn 1000010
using namespace std;int n, m;const int inf = 0x7fffffff;struct Edge{int to, next, w;
}edge[maxn << 3];int h[100010], cnt = 1;void add(int u, int v, int w){cnt ++;edge[cnt].to = v;edge[cnt].next = h[u];edge[cnt].w = w;h[u] = cnt;swap(u, v), w = 0;cnt ++;edge[cnt].to = v;edge[cnt].next = h[u];edge[cnt].w = w;h[u] = cnt;
}queue<int>Q;int d[100010], S, T;bool BFS(){memset(d, -1, sizeof d);Q.push(S);d[S] = 0;while(!Q.empty()){int u = Q.front();Q.pop();for(int i = h[u]; i; i = edge[i].next){if(!edge[i].w)continue;int v = edge[i].to;if(d[v] == -1){d[v] = d[u] + 1;Q.push(v);}}}return d[T] != -1;
}int DFS(int x, int a){if(x == T || a == 0)return a;int used = 0, f;for(int i = h[x]; i; i = edge[i].next){int v = edge[i].to;if(d[v] == d[x] + 1){f = DFS(v, min(a - used, edge[i].w));edge[i].w -= f;edge[i ^ 1].w += f;used += f;if(used == a)return used;}}if(used == 0)d[x] = -1;return used;
}int Dinic(){int ans = 0;while(BFS())ans += DFS(S, inf);return ans;
}int pos[110][110];const int dx[] = {0, 0, 1, -1};
const int dy[] = {1, -1, 0, 0};int main(){scanf("%d%d", &n, &m);S = 0, T = n * m + 1;int id = 0;for(int i = 1; i <= n; i ++)for(int j = 1; j <= m; j ++)pos[i][j] = ++ id;int total = 0, x;for(int i = 1; i <= n; i ++)for(int j = 1; j <= m; j ++){scanf("%d", &x);add(S, pos[i][j], x);total += x;}for(int i = 1; i <= n; i ++)for(int j = 1; j <= m; j ++){scanf("%d", &x);add(pos[i][j], T, x);total += x;}int size = T;for(int i = 1; i <= n; i ++)for(int j = 1; j <= m; j ++){scanf("%d", &x);total += x;++ size;add(S, size, x);add(size, pos[i][j], inf);for(int k = 0; k < 4; k ++){int u = dx[k] + i, v = dy[k] + j;if(pos[u][v])add(size, pos[u][v], inf);}}for(int i = 1; i <= n; i ++)for(int j = 1; j <= m; j ++){scanf("%d", &x);total += x;++ size;add(size, T, x);add(pos[i][j], size, inf);for(int k = 0; k < 4; k ++){int u = dx[k] + i, v = dy[k] + j;if(pos[u][v])add(pos[u][v], size, inf);}}printf("%d\n", total - Dinic());return 0;
}

[BZOJ 3894]文理分科相关推荐

  1. [BZOJ 3894]文理分科(最小割)

    Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行 描述,每个格子代表一个同学的座位.每位同 ...

  2. bzoj 3894: 文理分科 最小割

    Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠 结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行 描述,每个格子代表一个同学的座位.每位 ...

  3. bzoj 3894: 文理分科

    Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠 结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行 描述,每个格子代表一个同学的座位.每位 ...

  4. BZOJ 3894 文理分科

    题解:最小割建模 如果某些元素在一起会得到收益考虑最小割 答案 总收益-最小割 注意:对0点的处理 一开始模型是错的 #include<iostream> #include<cstd ...

  5. BZOJ 3894 文理分科 最小割

    题目大意:给定一个m*n的矩阵,每个格子的人可以学文或者学理,学文和学理各有一个满意度,如果以某人为中心的十字内所有人都学文或者学理还会得到一个额外满意度,求最大满意度之和 令S集为学文,T集为学理 ...

  6. BZOJ:3894: 文理分科(网络流)

    题目 每个同学都只能选择文科或者理科一种,选择文科会获得一个权值,理科也有,如果一个人以及周围四个人都选择了一个学科,那么又会获得一个权值. 将权值最大化. 分析 很经典的网络流题目,用最小割. 首先 ...

  7. 【BZOJ 3894】 文理分科

    3894: 文理分科 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 194 Solved: 122 [Submit][Status][Discuss] ...

  8. BZOJ3894:文理分科——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=3894 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠结过) 小P所在的班级要进行文理 ...

  9. 文理分科 (最小割问题)

    Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行描述,每个格子代表一个同学的座位.每位同学 ...

最新文章

  1. QIIME 2教程. 12数据筛选Filtering data(2020.11)
  2. 工作笔记--关于服务出问题时如何处理的流程
  3. 使用OpenMP实现多线程,不仅是用在循环处理上
  4. 双向链表的插入和删除算法描述
  5. v-for中用elementUI实现分页
  6. ***使用PHP实现文件上传和多文件上传
  7. 【详谈 Delta Lake 】系列技术专题 之 Streaming(流式计算)
  8. ofdm原理_OFDM技术简介
  9. enum中使用中文 unity_自定义Unity材质Inspector之枚举类型(Enum)
  10. SAP License:PO中“最终发票”的应用与理解
  11. Servlet3.0之八:基于Servlet3.0的文件上传@MultipartConfig
  12. 微服务系统和分布式系统的区别
  13. 超简单 Python 汉字拼音转换工具
  14. 机器人酷跑电脑版下载地址_机器人酷跑游戏
  15. MySQL原理与实践(四):由数据库事务引出数据库隔离级别
  16. python爬虫能爬取微信密码吗_爬虫如何爬取微信公众号文章
  17. TortoiseSVN文件夹及文件图标不显示解决方法
  18. xamarin学习笔记A19(安卓AIDL)
  19. 游戏随机地图生成方法
  20. 预览word,excel,ppt,pdf、图片————使用vue实现

热门文章

  1. jenkins Build periodically 参数配置
  2. VMProtect1.09分析
  3. 诺亚34亿爆雷,到底谁在说谎?
  4. [Unity]EasyTouch手指滑动返回距离值
  5. 记一次amd平台win10/win11随机死机蓝屏重启的问题
  6. A段架构师技术的十个学习步骤演练
  7. ICPC训练联盟2021寒假冬令营(9)_2021.01.29_笔记
  8. 2.1虚拟机及相关知识。
  9. saoml三合一app授权
  10. 【python】使用xlwt、xlrd、xlutils、openpyxl操作excel