如果没有组合效益的存在 我们直接每个点两部分的最大值即可

换成网络流模型来看 即把S点看作是A田 把T点看作是B田 每种作物看作一个点 分别连边(S,i,A[i]) (i,T,B[i])

最后图中所有边权和减去最大流即为答案.这个很好理解,因为最小割=最大流,一种作物只能选择A,B里的一个

所以对于每个点必要删去一条边,删去的边相当于我们不要的选项 剩下的和S,T相连的边相当于我们的选择 此时删去的肯定是最小的边.

接下来我们要处理组合效应的问题.

每个组合效应有三种选择:A/B/无

这样对于每个组合只建一个点很难满足要求 则我们把每个组合拆成A,B两个点  A点和S建边(S,A,C1[i])  B点和T建边(B,T,C2[i]) 表示选择A,B能得到的贡献.

再对于组合里的每个数都连边(A,K[i],INF) (K[i],B,INF) 这样图中除边权为INF的边的边权减去跑出来的最大流即为答案.

为什么这样跑出来即是我们选择要删去的选项?

因为最小割不可能会割INF的边

每个组合效应的A点 他旗下的每个点要都选A他才能产生贡献,如果有一个选了B则会产生增广路径,那么就必须要割掉(S,A,C1[i])

每个组合效应的B点 他旗下的每个点要都选B他才能产生贡献,如果有一个选了A则同样会产生增广路径,必须要割掉(B,T,C2[i])

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <queue>
  4. using namespace std;
  5. const int N=;
  6. const int M=;
  7. const int inf=0x3f3f3f3f;
  8. int head[N],edge[M],to[M],next[M],cnt=;
  9. void add(int u,int v,int w)
  10. {
  11. to[++cnt]=v;next[cnt]=head[u];edge[cnt]=w;head[u]=cnt;
  12. to[++cnt]=u;next[cnt]=head[v];edge[cnt]=;head[v]=cnt;
  13. }
  14. int dep[N],used[N],pre[N],tot,s[N],ans,m,n,sum;
  15. queue <int > q;
  16. bool bfs()
  17. {
  18. while(!q.empty()) q.pop();
  19. q.push();
  20. memset(dep,,sizeof(dep));
  21. dep[]=;
  22. while(!q.empty()&&q.front()!=n+)
  23. {
  24. int u=q.front();
  25. q.pop();
  26. for(int i=head[u];i;i=next[i])
  27. {
  28. int v=to[i],w=edge[i];
  29. if(!dep[v]&&w)
  30. {
  31. dep[v]=dep[u]+;
  32. q.push(v);
  33. }
  34. }
  35. }
  36. return !q.empty();
  37. }
  38. int main()
  39. {
  40. scanf("%d",&n);
  41. int w,v,k,c1,c2;
  42. for(int i=;i<=n;i++)
  43. {
  44. scanf("%d",&w);
  45. sum+=w;
  46. add(,i,w);
  47. }
  48. for(int i=;i<=n;i++)
  49. {
  50. scanf("%d",&w);
  51. sum+=w;
  52. add(i,n+,w);
  53. }
  54. scanf("%d",&m);
  55. for(int i=;i<=m;i++)
  56. {
  57. scanf("%d%d%d",&k,&c1,&c2);
  58. add(,i+n+,c1);sum+=c1;
  59. add(i+n+m+,n+,c2);sum+=c2;
  60. for(int j=;j<=k;j++)
  61. {
  62. scanf("%d",&v);
  63. add(i+n+,v,inf);
  64. add(v,i+n+m+,inf);
  65. }
  66. }
  67. while(bfs())
  68. {
  69. memset(used,,sizeof(used));
  70. s[++tot]=;
  71. while(tot)
  72. {
  73. int u=s[tot];
  74. if(u==n+)
  75. {
  76. int mi=inf,id;
  77. for(int i=tot;i>;i--)
  78. if(mi>=edge[pre[s[i]]])
  79. {
  80. mi=edge[pre[s[i]]];
  81. id=i;
  82. }
  83. ans+=mi;
  84. for(int i=tot;i>;i--)
  85. {
  86. edge[pre[s[i]]]-=mi;
  87. edge[pre[s[i]]^]+=mi;
  88. }
  89. tot=id-;
  90. used[n+]=;
  91. }
  92. else
  93. {
  94. for(int i=head[u];i;i=next[i])
  95. {
  96. int v=to[i],w=edge[i];
  97. if(!used[v]&&dep[v]==dep[u]+&&w)
  98. {
  99. used[v]=;
  100. s[++tot]=v;
  101. pre[v]=i;
  102. break;
  103. }
  104. }
  105. if(u==s[tot]) tot--;
  106. }
  107. }
  108. }
  109. printf("%d\n",sum-ans);
  110. return ;
  111. }

P1361 小M的作物 最小割理解的更多相关文章

  1. 洛谷 - P1361 - 小M的作物 - 最小割 - 最大权闭合子图

    第一次做最小割,不是很理解. https://www.luogu.org/problemnew/show/P1361 要把东西分进两类里,好像可以应用最小割的模板,其中一类A作为源点,另一类B作为汇点 ...

  2. [P1361] 小M的作物 - 最小割

    没想到今天早上的第一题网络流就血了这么多发 从经典的二选一问题上魔改 仍然考虑最小割 #include <bits/stdc++.h> using namespace std; #defi ...

  3. BZOJ 3438: 小M的作物( 最小割 )

    orz出题人云神... 放上官方题解... 转成最小割然后建图跑最大流就行了... ---------------------------------------------------------- ...

  4. BZOJ3438小M的作物——最小割

    题目描述 小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子 有1个(就是可以种一棵作物)(用1...n编号),现在,第i种作物种植在A中种植可 ...

  5. 【BZOJ3438】小M的作物 最小割

    [BZOJ3438]小M的作物 Description 小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子 有1个(就是可以种一棵作物)(用1. ...

  6. 3438: 小M的作物[最小割]

    3438: 小M的作物 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1073  Solved: 465[Submit][Status][Discus ...

  7. 【BZOJ-3438】小M的作物 最小割 + 最大权闭合图

    3438: 小M的作物 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 825  Solved: 368[Submit][Status][Discuss ...

  8. 小M的作物 最小割最大流

    题目描述 小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子有1个(就是可以种一棵作物)(用1...n编号). 现在,第i种作物种植在A中种植可 ...

  9. 洛谷 P1361 小M的作物 解题报告

    P1361 小M的作物 题目描述 小M在MC里开辟了两块巨大的耕地\(A\)和\(B\)(你可以认为容量是无穷),现在,小\(P\)有\(n\)中作物的种子,每种作物的种子有1个(就是可以种一棵作物) ...

随机推荐

  1. centos(linux)--vsftpd配置

    1.安装 执行 yum -y install vsftpd 注:(1)是否使用sudo权限根据个人的具体情况 (2)rpm -qa | grep vsftpd 可以通过这个检查是否已经安装vsftpd ...

  2. 01.03 vim编辑器使用

    ==========linux基础命令的使用==========================绝对路径:由根目录(/)开始写起的文件名或目录名称相对路径:相对于目前路径的文件名写法(开头不是/就属于 ...

  3. 【DSP开发】6455EMIF

     外部设备连接接口包括外部存储器连接接口(EMIF).主机接口(HPI)等.外部存储器接口主要用来同并行存储器连接,这些存储器包括SDRAM.SBSRAM.Flash.SRAM存储器等,外部存储器接口 ...

  4. 【SVN】总结:svn“Previous operation has not finished; run 'cleanup' if it was interrupted“

    svn执行clean up命令时报错“Previous operation has not finished; run 'cleanup' if it was interrupted”.无论你到那个父 ...

  5. Gradle DSL Walle渠道包后安装启动APP

    DSL(Domain-Specific Language) Gradle 是一个编译打包工具,但实际上它也是一个编程框架. Task 是 Gradle 中的一种数据类型,它代表了一些要执行或者要干的工 ...

  6. SQL SERVER YEAR函数

    定义: YEAR函数返回指定日期的年的部分 语法: YEAR(date) 参数: ①date参数是合法的日期表达式. 返回值: int型数据 例:  声明:本文是本人查阅网上及书籍等各种资料,再加上自 ...

  7. mysql中比较实用的几个函数

    1.曾有这样的需求: 可以使用如下函数: 语法:FIND_IN_SET(str,strlist). 定义: 1. 假如字符串str在由N子链组成的字符串列表strlist中,则返回值的范围在1到N之间 ...

  8. Dao设计模式简单实现

    一.什么是Dao设计模式 Dao设计模式封装了操作具体数据库的细节,对业务层提供操作数据库的接口,因此降低了业务层代码与具体数据库之间的耦合,有利于人员分工,增加了程序的可移植性. Dao设计模式中主 ...

  9. 【hash】Seek the Name, Seek the Fame

    [哈希和哈希表]Seek the Name, Seek the Fame 题目描述 The little cat is so famous, that many couples tramp over ...

  10. android中sqlite数据库的基本使用和添加多张表

    看了很多关于android使用sqlite数据库的文章,很多都是介绍了数据库的建立和表的建立,而表通常都是只建立一张,而实际情况我们用到的表可能不止一张,那这种情况下我们又该怎么办呢,好了,下面我教大 ...