#2205. 「HNOI2014」画框

最小乘积生成树+KM二分图带权匹配

维护一个\((\sum A,\sum B)\)的匹配下凸包,答案在这些点中产生。

具体的,凸包两端可以直接跑单独的\(A\)权与\(B\)权的最小带权匹配

然后进行分治,每次找离线段的最远点加入匹配

用叉积推一下式子可以得到进行匹配的图的边权,然后继续跑KM就可以了


Code:

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #define yuucute 1
  5. const int N=80;
  6. using std::min;
  7. using std::max;
  8. struct Point
  9. {
  10. int x,y;
  11. Point(){x=0,y=0;}
  12. Point(int X,int Y){x=X,y=Y;}
  13. Point friend operator -(Point a,Point b){return Point(a.x-b.x,a.y-b.y);}
  14. };
  15. int Cross(Point a,Point b){return a.x*b.y-a.y*b.x;}
  16. int va[N],vb[N],w[N][N],a[N][N],b[N][N],mat[N],la[N],lb[N],n,mi,ans;
  17. bool dfs(int now)
  18. {
  19. va[now]=1;
  20. for(int v=1;v<=n;v++)
  21. if(!vb[v])
  22. {
  23. if(w[now][v]==la[now]+lb[v])
  24. {
  25. vb[v]=1;
  26. if(!mat[v]||dfs(mat[v]))
  27. return mat[v]=now,true;
  28. }
  29. else mi=min(mi,la[now]+lb[v]-w[now][v]);
  30. }
  31. return false;
  32. }
  33. Point KM()
  34. {
  35. memset(mat,0,sizeof mat);
  36. for(int i=1;i<=n;i++)
  37. {
  38. la[i]=-(1<<30);
  39. lb[i]=0;
  40. for(int j=1;j<=n;j++)
  41. la[i]=max(la[i],w[i][j]);
  42. }
  43. for(int i=1;i<=n;i++)
  44. {
  45. while(yuucute)
  46. {
  47. memset(va,0,sizeof va);
  48. memset(vb,0,sizeof vb);
  49. mi=1<<30;
  50. if(dfs(i)) break;
  51. for(int j=1;j<=n;j++)
  52. {
  53. if(va[j]) la[j]-=mi;
  54. if(vb[j]) lb[j]+=mi;
  55. }
  56. }
  57. }
  58. Point ret;
  59. for(int i=1;i<=n;i++) ret.x+=a[mat[i]][i],ret.y+=b[mat[i]][i];
  60. return ret;
  61. }
  62. void Divide(Point A,Point B)
  63. {
  64. for(int i=1;i<=n;i++)
  65. for(int j=1;j<=n;j++)
  66. w[i][j]=a[i][j]*(B.y-A.y)-b[i][j]*(B.x-A.x);
  67. Point C=KM();
  68. if(Cross(C-A,B-A)<=0) return;
  69. ans=min(ans,C.x*C.y);
  70. Divide(A,C),Divide(C,B);
  71. }
  72. void work()
  73. {
  74. scanf("%d",&n);
  75. for(int i=1;i<=n;i++)
  76. for(int j=1;j<=n;j++)
  77. scanf("%d",&a[i][j]);
  78. for(int i=1;i<=n;i++)
  79. for(int j=1;j<=n;j++)
  80. scanf("%d",&b[i][j]);
  81. for(int i=1;i<=n;i++)
  82. for(int j=1;j<=n;j++)
  83. w[i][j]=-a[i][j];
  84. Point A=KM();
  85. ans=A.x*A.y;
  86. for(int i=1;i<=n;i++)
  87. for(int j=1;j<=n;j++)
  88. w[i][j]=-b[i][j];
  89. Point B=KM();
  90. ans=min(ans,B.x*B.y);
  91. Divide(A,B);
  92. printf("%d\n",ans);
  93. }
  94. int main()
  95. {
  96. int T;scanf("%d",&T);
  97. while(T--) work();
  98. return 0;
  99. }

2019.2.19

LOJ #2205. 「HNOI2014」画框 解题报告的更多相关文章

  1. 【LOJ】#2205. 「HNOI2014」画框

    题解 我原来根本不会KM 更新每个节点增加的最小值的时候,要忽略那个方访问过的右节点!!! 然后就和最小乘积生成树一样了 代码 #include <iostream> #include & ...

  2. 「ZJOI2016」旅行者 解题报告

    「ZJOI2016」旅行者 对网格图进行分治. 每次从中间选一列,然后枚举每个这一列的格子作为起点跑最短路,进入子矩形时把询问划分一下,有点类似整体二分 至于复杂度么,我不会阿 Code: #incl ...

  3. 「HNOI2016」树 解题报告

    「HNOI2016」树 事毒瘤题... 我一开始以为每次把大树的子树再接给大树,然后死活不知道咋做,心想怕不是个神仙题哦 然后看题解后才发现是把模板树的子树给大树,虽然思维上难度没啥了,但是还是很难写 ...

  4. 「HNOI2016」序列 解题报告

    「HNOI2016」序列 有一些高妙的做法,懒得看 考虑莫队,考虑莫队咋移动区间 然后你在区间内部找一个最小值的位置,假设现在从右边加 最小值左边区间显然可以\(O(1)\),最小值右边的区间是断掉的 ...

  5. 「HNOI2016」网络 解题报告

    「HNOI2016」网络 我有一个绝妙的可持久化树套树思路,可惜的是,它的空间是\(n\log^2 n\)的... 注意到对一个询问,我们可以二分答案 然后统计经过这个点大于当前答案的路径条数,如果这 ...

  6. 「HAOI2018」染色 解题报告

    「HAOI2018」染色 是个套路题.. 考虑容斥 则恰好为\(k\)个颜色恰好为\(c\)次的贡献为 \[ \binom{m}{k}\sum_{i\ge k}(-1)^{i-k}\binom{m-k ...

  7. 「HNOI2016」最小公倍数 解题报告

    「HNOI2016」最小公倍数 考虑暴力,对每个询问,处理出\(\le a,\le b\)的与询问点在一起的联通块,然后判断是否是一个联通块,且联通块\(a,b\)最大值是否满足要求. 然后很显然需要 ...

  8. 「SCOI2016」围棋 解题报告

    「SCOI2016」围棋 打CF后困不拉基的,搞了一上午... 考虑直接状压棋子,然后发现会t 考虑我们需要上一行的状态本质上是某个位置为末尾是否可以匹配第一行的串 于是状态可以\(2^m\)压住了, ...

  9. 「SCOI2016」妖怪 解题报告

    「SCOI2016」妖怪 玄妙...盲猜一个结论,然后过了,事后一证,然后假了,数据真水 首先要最小化 \[ \max_{i=1}^n (1+k)x_i+(1+\frac{1}{k})y_i \] \ ...

随机推荐

  1. Python之random模块

    random模块 产生随机数的模块 是Python的标准模块,直接导入即可 import random 1)随机取一个整数,使用.randint()方法: import random print(ra ...

  2. react初入门

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. scrapy全站爬取拉勾网及CrawSpider介绍

    一.指定模板创建爬虫文件 命令 创建成功后的模板,把http改为https 二.CrawSpider源码介绍 1.官网介绍: 这是用于抓取常规网站的最常用的蜘蛛,因为它通过定义一组规则为跟踪链接提供了 ...

  4. shell中数组及其相关操作

    转载 https://blog.csdn.net/jerry_1126/article/details/52027539

  5. ajax获得后台传来的一个json值,在js中获得其中的属性值

    首先 ajax的dataType需要设置为json, 默认的text获取属性值在jquery3.2.1中尝试不成功 获得属性值的方式: 类似数组,键值对的方式 下面例子: 设置dataType为jso ...

  6. layui loading

    layer.msg('加载中', { icon: 16 ,shade: 0.4}); layer.load(2);风格二 setTimeout(function(){ layer.closeAll(' ...

  7. 吴恩达deeplearning之CNN—卷积神经网络

    https://blog.csdn.net/ice_actor/article/details/78648780 个人理解: 卷积计算的过程其实是将原始的全连接换成了卷积全连接,每个kernel为对应 ...

  8. MySQL的my.cnf文件(解决5.7.18下没有my-default.cnf)

    官网说:从5.7.18开始不在二进制包中提供my-default.cnf文件.参考:https://dev.mysql.com/doc/refman/5.7/en/binary-installatio ...

  9. IntelliJ IDEA 导航的 20 大特性

    本文由 ImportNew - elviskang 翻译自 dzone.欢迎加入翻译小组.转载请见文末要求. 在前面的文章里,我介绍了IntelliJ IDEA(以下称IntelliJ)中与代码补全及 ...

  10. 利用kali破解wifi密码

    准备工具 1.笔记本 2.USB无线上网卡(必备) 3.kali系统 4.密码字典 第一种方法 暴力破解法 何为暴力破解呢,其实就是一个一个密码去试,直到正确的密码. 现在的wifi一般加密都是: 1 ...