题目链接:BZOJ - 2007

题目分析

首先,左上角的高度是 0 ,右下角的高度是 1。那么所有点的高度一定要在 0 与 1 之间。然而选取 [0, 1] 的任何一个实数,都可以用整数 0 或 1 来替换,获得同样的效果。

虽然输出的答案要求是四舍五入到整数,但其实答案就是一个整数!

那么高度就一定是 0 或 1 了,并且还有一点,所有选 0 的点都连通,所有选 1 的点都联通。因为如果一个选 0 的点被选 1 的点包围,那么它选 1 更优。

于是整个图中所有的点分成了与左上角相连的集合 A ,与右下角相连的集合 B 。从集合 A 向 B 的边权会计入答案。这就是最小割模型。

这是一个规则的平面图,平面图最小割等于对偶图最短路

建立对偶图:

1)增加一条从 S 到 T 的边,成为 ST 边。这条边把原图中外围无限大的平面部分分割成了一个有限部分 S’ 和无限部分 T’。S’ 与 T’ 就是对偶图的起点和终点。

2)将平面的每个部分看做一个虚拟点,每条边对应一条连接虚拟点的边。但是 ST 边不对应对偶图中的边。

对偶图的一条最短路就对应了原图的一个最小割。

原图的每一条单向边对应对偶图的边的方向可以画个图帮助确定。可以看看从 S’ 到 T’ 的路径中哪些方向的边计入最小割答案,也应是最短路答案。

写 dijkstra !卡 SPFA!

代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <cmath>
  6. #include <algorithm>
  7. #include <queue>
  8.  
  9. using namespace std;
  10.  
  11. const int MaxN = 500 + 5, INF = 999999999;
  12.  
  13. int n, S, T;
  14. int Map[MaxN][MaxN][5], d[MaxN * MaxN];
  15.  
  16. bool Visit[MaxN * MaxN];
  17.  
  18. inline int Calc(int x, int y) {return (x - 1) * n + y;}
  19.  
  20. struct Edge
  21. {
  22. int v, w;
  23. Edge *Next;
  24. } E[MaxN * MaxN * 4], *P = E, *Point[MaxN * MaxN];
  25.  
  26. inline void AddEdge(int x, int y, int z) {
  27. ++P; P -> v = y; P -> w = z;
  28. P -> Next = Point[x]; Point[x] = P;
  29. }
  30.  
  31. struct ES
  32. {
  33. int x, y;
  34. ES() {}
  35. ES(int a, int b) {
  36. x = a; y = b;
  37. }
  38. };
  39.  
  40. struct Cmp
  41. {
  42. bool operator () (ES e1, ES e2) {
  43. return e1.y > e2.y;
  44. }
  45. };
  46.  
  47. priority_queue<ES, vector<ES>, Cmp> Q;
  48.  
  49. int main()
  50. {
  51. scanf("%d", &n);
  52. //Input data...
  53. for (int i = 1; i <= n + 1; ++i)
  54. for (int j = 1; j <= n; ++j)
  55. scanf("%d", &Map[i][j][0]);
  56. for (int i = 1; i <= n; ++i)
  57. for (int j = 1; j <= n + 1; ++j)
  58. scanf("%d", &Map[i][j][1]);
  59. for (int i = 1; i <= n + 1; ++i)
  60. for (int j = 2; j <= n + 1; ++j)
  61. scanf("%d", &Map[i][j][2]);
  62. for (int i = 2; i <= n + 1; ++i)
  63. for (int j = 1; j <= n + 1; ++j)
  64. scanf("%d", &Map[i][j][3]);
  65. //Input done...
  66. S = n * n + 1; T = n * n + 2;
  67. for (int i = 1; i <= n + 1; ++i) {
  68. for (int j = 1; j <= n + 1; ++j) {
  69. if (j <= n) {
  70. if (i == 1) AddEdge(Calc(i, j), T, Map[i][j][0]);
  71. else if (i == n + 1) AddEdge(S, Calc(i - 1, j), Map[i][j][0]);
  72. else AddEdge(Calc(i, j), Calc(i - 1, j), Map[i][j][0]);
  73. }
  74. if (j > 1) {
  75. if (i == 1) AddEdge(T, Calc(i, j - 1), Map[i][j][2]);
  76. else if (i == n + 1) AddEdge(Calc(i - 1, j - 1), S, Map[i][j][2]);
  77. else AddEdge(Calc(i - 1, j - 1), Calc(i, j - 1), Map[i][j][2]);
  78. }
  79. if (i <= n) {
  80. if (j == 1) AddEdge(S, Calc(i, j), Map[i][j][1]);
  81. else if (j == n + 1) AddEdge(Calc(i, j - 1), T, Map[i][j][1]);
  82. else AddEdge(Calc(i, j - 1), Calc(i, j), Map[i][j][1]);
  83. }
  84. if (i > 1) {
  85. if (j == 1) AddEdge(Calc(i - 1, j), S, Map[i][j][3]);
  86. else if (j == n + 1) AddEdge(T, Calc(i - 1, j - 1), Map[i][j][3]);
  87. else AddEdge(Calc(i - 1, j), Calc(i - 1, j - 1), Map[i][j][3]);
  88. }
  89. }
  90. }
  91. //Build_Edge done...
  92. memset(Visit, 0, sizeof(Visit));
  93. for (int i = 1; i <= T; ++i) d[i] = INF;
  94. d[S] = 0;
  95. while (!Q.empty()) Q.pop();
  96. ES Now;
  97. for (int i = 1; i <= T; ++i) Q.push(ES(i, d[i]));
  98. while (!Q.empty()) {
  99. Now = Q.top(); Q.pop();
  100. if (Visit[Now.x]) continue;
  101. if (Now.x == T) break;
  102. Visit[Now.x] = true;
  103. for (Edge *j = Point[Now.x]; j; j = j -> Next) {
  104. if (d[Now.x] + j -> w < d[j -> v]) {
  105. d[j -> v] = d[Now.x] + j -> w;
  106. Q.push(ES(j -> v, d[j -> v]));
  107. }
  108. }
  109. }
  110. printf("%d\n", d[T]);
  111. return 0;
  112. }

  

[BZOJ 2007] [Noi2010] 海拔 【平面图最小割(对偶图最短路)】的更多相关文章

  1. bzoj 2007: [Noi2010]海拔【最小割+dijskstra】

    上来就跑3e5的最大流--脑子抽了 很容易看出,每个地方的海拔都是0或1因为再高了没有意义,又,上去下来再上去没有意义,所以最后一定是从s连着一片0,剩下连着t一片1,然后有贡献的就是01交接的那些边 ...

  2. Vijos1734 NOI2010 海拔 平面图最小割

    建立平面图的对偶图,把最小割转化成最短路问题 Dijkstra算法堆优化 (被输入顺序搞WA了好几次T_T) #include <cstdio> #include <cstring& ...

  3. bzoj2007/luoguP2046 海拔(平面图最小割转对偶图最短路)

    bzoj2007/luoguP2046 海拔(平面图最小割转对偶图最短路) 题目描述: bzoj  luogu 题解时间: 首先考虑海拔待定点的$h$都应该是多少 很明显它们都是$0$或$1$,并且所 ...

  4. 【BZOJ1001】狼抓兔子(平面图最小割转最短路)

    题意:有一张平面图,求它的最小割.N,M.表示网格的大小,N,M均小于等于1000. 左上角点为(1,1),右下角点为(N,M).有以下三种类型的道路  1:(x,y)<==>(x+1,y ...

  5. BZOJ.2007.[NOI2010]海拔(最小割 对偶图最短路)

    题目链接 想一下能猜出,最优解中海拔只有0和1,且海拔相同的点都在且只在1个连通块中. 这就是个平面图最小割.也可以转必须转对偶图最短路,不然只能T到90分了..边的方向看着定就行. 不能忽略回去的边 ...

  6. BZOJ 2007 海拔(平面图最小割转对偶图最短路)

    首先注意到,把一个点的海拔定为>1的数是毫无意义的.实际上,可以转化为把这些点的海拔要么定为0,要么定为1. 其次,如果一个点周围的点的海拔没有和它相同的,那么这个点的海拔也是可以优化的,即把这 ...

  7. BZOJ2007/LG2046 「NOI2010」海拔 平面图最小割转对偶图最短路

    问题描述 BZOJ2007 LG2046 题解 发现左上角海拔为 \(0\) ,右上角海拔为 \(1\) . 上坡要付出代价,下坡没有收益,所以有坡度的路越少越好. 所以海拔为 \(1\) 的点,和海 ...

  8. BZOJ 2007: [Noi2010]海拔

    2007: [Noi2010]海拔 Time Limit: 20 Sec  Memory Limit: 552 MBSubmit: 2410  Solved: 1142[Submit][Status] ...

  9. 洛谷P2046 [NOI2010]海拔(最小割,平面图转对偶图)

    传送门 不明白为什么大佬们一眼就看出这是最小割…… 所以总而言之这就是一个最小割我也不知道为什么 然后边数太多直接跑会炸,所以要把平面图转对偶图,然后跑一个最短路即可 至于建图……请看代码我实在无能为 ...

随机推荐

  1. Eclipse中修改SVN用户名和密码方法

    于在svn 的界面中并没有为我们提供直接更换用户名密码的地方,所以一旦我们需要更换用户名的就需要自己想一些办法. 解决方案: 在Eclipse 使用SVN 的过程中大多数人往往习惯把访问SVN 的用户 ...

  2. 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(38)-Easyui-accordion+tree漂亮的菜单导航

    原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(38)-Easyui-accordion+tree漂亮的菜单导航 系列目录 本节主要知识点是easyui ...

  3. System.in与System.out(标准输入与标准输出)详解

    package test; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; p ...

  4. DSPack各种使用方法

    1. DSPack 2.3.4 安装   一. 下载由于sourceforge最近不能访问,所以可以去 http://www.progdigy.com/ 下载.下载 http://www.progdi ...

  5. 基于Android 4.4 开发的多窗体系统 开放源代码

    Hi, 这是我基于Android 4.4开发的多窗体系统,还有非常多不足,还请多多不吝赐教啊,代码已经所有开源. 视频地址 源代码地址 Done: 1. APP以窗体化显示 在 PhoneWindow ...

  6. python模拟登陆之下载

    好长时间没有更新博客了,哈哈. 今天公司给了这么一个需求,现在我们需要去淘宝获取上一天的订单号,然后再根据订单号去另一个接口去获取订单详情,然后再给我展示到web! 中间涉及到的技术点有: 模拟登陆 ...

  7. #IOS-navigation中左滑pop的三种方法

    IOS-navigation中左滑pop的三种方法 系统自带pop方法 如果我们没有对navigation中的back按钮进行自定义,我们可以直接使用系统自带的左滑pop方法.但是如果我们对back按 ...

  8. 自己写的Dapper通用数据访问层

    using Microsoft.Practices.EnterpriseLibrary.Data; using Microsoft.Practices.EnterpriseLibrary.Data.O ...

  9. RHEL7安装配置TigerVNC

    TigerVNC使用非加密的链接,默认会被firewalld blocked 掉,想要 vnc正常工作就需要让firewalld开放相应的端口才行. vnc默认的端口号为5900,而每个vnc win ...

  10. oracle过滤分割字符串自定义函数

    该函数实现过滤前后的指定的字符串,诸如过滤分隔符等.可用于过滤字符串中的逗号分割符.特别说明:substr()函数支持从字符串倒数开始读取,例如: dbms_output.put_line( subs ...