$ \color{#0066ff}{ 题目描述 }$

文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠结过)

小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想知道,大家应该如何选择,才能使所有人的满意值之和最大。请告诉他这个最大值。

\(\color{#0066ff}{输入格式}\)

第一行为两个正整数:n,m

接下来n行m个整数,表示art[i][j];

接下来n行m个整数.表示science[i][j];

接下来n行m个整数,表示same_art[i][j];

接下来n行m个整数,表示same_science[i][j];

\(\color{#0066ff}{输出格式}\)

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

\(\color{#0066ff}{输入样例}\)

  1. 3 4
  2. 13 2 4 13
  3. 7 13 8 12
  4. 18 17 0 5
  5. 8 13 15 4
  6. 11 3 8 11
  7. 11 18 6 5
  8. 1 2 3 4
  9. 4 2 3 2
  10. 3 1 0 4
  11. 3 2 3 2
  12. 0 2 2 1
  13. 0 2 4 4

\(\color{#0066ff}{输出样例}\)

  1. 152

\(\color{#0066ff}{数据范围与提示}\)

1表示选择文科,0表示选择理科,方案如下:

1 0 0 1

0 1 0 0

1 0 0 0

N,M<=100,读入数据均<=500

\(\color{#0066ff}{题解}\)

根据题目,每个人要么选文,要么选理,当然是最小割了

然后我们考虑建图

首先最基本的,显然可以弄出n*m个点,s向这些点连文科的边,这些点向t连理科的边

割掉哪个哪个不选

对于每一个额外的值,只要那些人中有一个人没符合要求,就必须剪掉!

也就是说,如果不割掉,那么就联通了

可以建立一个虚点,s向虚点连文科额外的分,这个虚点向对应的\(1-5\)个点连inf的边(割不了)

这样的话,理科有一个边没割(代表有人选理)就不会获得文科额外价值,理科同理也建立虚点

最后总共的-最大流(最小割)即可

  1. #include<bits/stdc++.h>
  2. #define LL long long
  3. LL in() {
  4. char ch; LL x = 0, f = 1;
  5. while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
  6. for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
  7. return x * f;
  8. }
  9. const int inf = 0x7ffffff;
  10. const int maxn = 1e5 + 10;
  11. const int maxm = 120;
  12. struct node {
  13. int to, can;
  14. node *nxt, *rev;
  15. node(int to = 0, int can = 0, node *nxt = NULL): to(to), can(can), nxt(nxt) { rev = NULL; }
  16. };
  17. node *head[maxn], *cur[maxn];
  18. int dep[maxn];
  19. int wen[maxm][maxm], li[maxm][maxm], ww[maxm][maxm], ll[maxm][maxm];
  20. int n, m, s, t, tot;
  21. bool bfs() {
  22. for(int i = s; i <= t; i++) dep[i] = 0, cur[i] = head[i];
  23. std::queue<int> q;
  24. dep[s] = 1;
  25. q.push(s);
  26. while(!q.empty()) {
  27. int tp = q.front(); q.pop();
  28. for(node *i = head[tp]; i; i = i->nxt)
  29. if(!dep[i->to] && i->can)
  30. dep[i->to] = dep[tp] + 1, q.push(i->to);
  31. }
  32. return dep[t];
  33. }
  34. int dfs(int x, int change) {
  35. if(x == t || !change) return change;
  36. int flow = 0, ls;
  37. for(node *&i = cur[x]; i; i = i->nxt) {
  38. if(dep[i->to] == dep[x] + 1 && (ls = dfs(i->to, std::min(change, i->can)))) {
  39. flow += ls;
  40. change -= ls;
  41. i->can -= ls;
  42. i->rev->can += ls;
  43. if(!change) break;
  44. }
  45. }
  46. return flow;
  47. }
  48. int id(int x, int y) { return (x - 1) * m + y; }
  49. void add(int from, int to, int can) {
  50. head[from] = new node(to, can, head[from]);
  51. }
  52. void link(int from, int to, int can) {
  53. add(from, to, can), add(to, from, 0);
  54. (head[from]->rev = head[to])->rev = head[from];
  55. }
  56. int dinic() {
  57. int flow = 0;
  58. while(bfs()) flow += dfs(s, inf);
  59. return flow;
  60. }
  61. int main() {
  62. n = in(), m = in();
  63. for(int i = 1; i <= n; i++)
  64. for(int j = 1; j <= m; j++)
  65. wen[i][j] = in();
  66. for(int i = 1; i <= n; i++)
  67. for(int j = 1; j <= m; j++)
  68. li[i][j] = in();
  69. for(int i = 1; i <= n; i++)
  70. for(int j = 1; j <= m; j++)
  71. ww[i][j] = in();
  72. for(int i = 1; i <= n; i++)
  73. for(int j = 1; j <= m; j++)
  74. ll[i][j] = in();
  75. int tot = 0;
  76. s = 0, t = 3 * n * m + 1;
  77. for(int i = 1; i <= n; i++)
  78. for(int j = 1; j <= m; j++) {
  79. tot += wen[i][j];
  80. link(s, id(i, j), wen[i][j]);
  81. tot += li[i][j];
  82. link(id(i, j), t, li[i][j]);
  83. }
  84. int now = n * m;
  85. for(int i = 1; i <= n; i++)
  86. for(int j = 1; j <= m; j++) {
  87. now++;
  88. link(s, now, ww[i][j]), tot += ww[i][j];
  89. link(now, id(i, j), inf);
  90. if(i != 1) link(now, id(i - 1, j), inf);
  91. if(i != n) link(now, id(i + 1, j), inf);
  92. if(j != 1) link(now, id(i, j - 1), inf);
  93. if(j != m) link(now, id(i, j + 1), inf);
  94. }
  95. for(int i = 1; i <= n; i++)
  96. for(int j = 1; j <= m; j++) {
  97. now++;
  98. link(now, t, ll[i][j]), tot += ll[i][j];
  99. link(id(i, j), now, inf);
  100. if(i != 1) link(id(i - 1, j), now, inf);
  101. if(i != n) link(id(i + 1, j), now, inf);
  102. if(j != 1) link(id(i, j - 1), now, inf);
  103. if(j != m) link(id(i, j + 1), now, inf);
  104. }
  105. printf("%d\n", tot - dinic());
  106. return 0;
  107. }

P4313 文理分科 最小割的更多相关文章

  1. BZOJ 3894 Luogu P4313 文理分科 (最小割)

    题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=3894 (luogu) https://www.luogu.org/pro ...

  2. BZOJ3894文理分科——最小割

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

  3. BZOJ 3894: 文理分科 [最小割]

    3894: 文理分科 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 674  Solved: 392[Submit][Status][Discuss] ...

  4. 【BZOJ3894】【Luogu3358】文理分科 - 最小割多选一模型

    链接Click Here 这个题就是个板子的最小割多选一模型啦\(QwQ\),这里介绍一种通用的解法. 抛开组合收益不谈,这个题就是一个简单的最小割模型.我们只需要建出来这样一张图,在上面跑最小割,割 ...

  5. 【BZOJ3894】文理分科 最小割

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

  6. [BZOJ3894]文理分科(最小割)

    (1) 对每个位置建一个点F1,S向这个点连art[i][j]的边,这个点向T连science[i][j]的边. (2) 对每个位置再建一个点F2,S向这个点连same_art[i][j]的边,这个点 ...

  7. BZOJ3894/LuoguP4313 文理分科 (最小割)

    #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> ...

  8. P4313 文理分科

    思路 遇到这种利益冲突的最终利益最大化问题 考虑转化为最小割,使得损失的价值最小 相当于文科是S,理科是T,选出最小割就是确定损失代价最小的方案 然后就把S向每个点连一条cap=art[i][j]的边 ...

  9. Luogu P4313 文理分科

    link 最小割 双倍经验 这道题运用了最小割最常用的一种用法:集合划分. 因为源汇最小割即就是将源汇划分到不同的集合,那么最简单的应用就是最小代价划分集合了. 本题中,题意是将 \(n\cdot m ...

随机推荐

  1. How to Change Master Page @ Run-time

    This tip will give complete knowledge of how to change master page, render controls and accessing it ...

  2. MySQL备份还原之二使用mysqldump

    1 场景描述: create table gyj_t1(id int,name varchar(10)); insert into gyj_t1 values(1,'AAAAA'); commit; ...

  3. 音频AAC编码浅析

    /* * unsigned long nSampleRate, // 采样率,单位是bps * unsigned long nChannels, // 声道,1为单声道,2为双声道 * unsigne ...

  4. wireshark怎么抓包、wireshark抓包详细图文教程(转)

    wireshark怎么抓包.wireshark抓包详细图文教程 wireshark是非常流行的网络封包分析软件,功能十分强大.可以截取各种网络封包,显示网络封包的详细信息.使用wireshark的人必 ...

  5. html收藏

    全屏显示<input type="button" name="fullscreen" value="全屏显示" onclick=&qu ...

  6. git用法小结(1)--建立远程仓库

    最近一直在学习使用git来管理自己的程序,总是今天东学一点,明天西凑一点,到用的时候,总是有些茫然不知所措. 在博客园里看见一篇老好的文章,教我们做笔记啦,但是做完笔记还是要记得总结哦! 来吧,让我们 ...

  7. XHProf安装使用笔记

    编译安装 获取源代码包root@sourcjoy>wget http://pecl.php.net/get/xhprof-0.9.2.tgz解压root@sourcjoy>tar zxf ...

  8. 【总结整理】关于GrowingIO、友盟、google analysis等数据分析

    作者:纯银V链接:https://www.jianshu.com/p/394ec6c96c98來源:简书简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处. 埋点主要分为四步:第一步是 ...

  9. 在Build Path中包含其他工程

    ------------siwuxie095                                 在 TestBuildPath 的 Build Path 中包含 SupportProje ...

  10. jmap, jhat命令

    jmap命令有下面几种常用的用法 jmap [pid] jmap -histo:live [pid] >a.log jmap -dump:live,format=b,file=xxx.xxx [ ...