\(\mathcal{Description}\)

  Link.

  给定一个 \(n\times n\) 的格点图,横纵相邻的两格点有一条边权为二元组 \((w,e)\) 的边。求对于 \(S=(1,1)\) 和 \(T=(n,n)\) 的一个割,使得 \((\sum w)(\sum c)\) 最小。

  \(n\le400\)。

\(\mathcal{Solution}\)

  套路题,P5540 + P4001。所以我把这两题题解合二为一。

  假设边权都是普通的数字,考虑怎么快速求出这个格点图的最小割。可以发现,这个图一定是一个平面图,那么把它形象化为图形,脑补一下得出一个割肯定是一条完整的曲线,从图的左下方贯穿到图的右上方。所以建立左下方和右上方的超级源汇,每条边相当于连接其左右两个面,最后求源汇之间的最短路即为原图最小割。

  回到本题,对于任意一个割,设其 \(\sum w=w_0\),\(\sum e=e_0\),将它体现为一个坐标 \((w_0,e_0)\),问题就转化为:\(\mathbb R^2\) 的一象限有若干个点,求出其中 \(xy\) 最小的点。

  记 \(A(x_1,y_1)\) 为这些点中 \(x\) 最小的,\(B(x_2,y_2)\) 为 \(y\) 最小的(都能直接求出),考虑在 \(AB\) 的下方取出一个特殊的点 \(C(x_3,y_3)\),最大化 \(S_{\triangle ABC}\)。推一下式子:

\[\begin{aligned}
S_{\triangle ABC}&=\frac{-\vec{AB}\times \vec{AC}}{2}\\
&=-\frac{1}{2}[(x_2-x_1)(y_3-y_1)-(x_3-x_1)(y_2-y_1)]\\
&=-\frac{1}2[(y_1-y_2)x_3+(x_2-x_1)y_3-x_2y_1+x_1y_2]
\end{aligned}
\]

  把 \((y_1-y_2)w+(x_2-x_1)e\) 作为边 \((w,e)\) 的权,跑最小割即得 \(C\)。用 \(C\) 更新答案最后,分治处理 \((A,C)\) 和 \((C,B)\) 直到 \(C\) 不存在终止,答案就求到啦。

\(\mathcal{Code}\)

  1. /* Clearink */
  2. #include <queue>
  3. #include <cstdio>
  4. #include <assert.h>
  5. typedef long long LL;
  6. inline int rint () {
  7. int x = 0, f = 1; char s = getchar ();
  8. for ( ; s < '0' || '9' < s; s = getchar () ) f = s == '-' ? -f : f;
  9. for ( ; '0' <= s && s <= '9'; s = getchar () ) x = x * 10 + ( s ^ '0' );
  10. return x * f;
  11. }
  12. inline void chkmin ( LL& a, const LL b ) { b < a && ( a = b, 0 ); }
  13. const int MAXN = 400, INF = 0x3f3f3f3f;
  14. int n, S, T;
  15. LL coeW, coeE, ans = 1ll << 60;
  16. struct Value {
  17. LL w, e;
  18. Value ( const LL v = 0 ): w ( v ), e ( v ) {}
  19. Value ( const LL a, const LL b ): w ( a ), e ( b ) {}
  20. inline operator LL () const { return w + e; }
  21. inline LL operator * ( const Value& v ) const { return w * v.e - e * v.w; }
  22. inline Value operator + ( const Value& v ) const { return { w + v.w, e + v.e }; }
  23. inline Value operator - ( const Value& v ) const { return { w - v.w, e - v.e }; }
  24. inline bool operator < ( const Value& v ) const {
  25. return coeW * w + coeE * e < coeW * v.w + coeE * v.e;
  26. }
  27. };
  28. typedef std::pair<Value, int> PVI;
  29. struct Graph {
  30. static const int MAXND = MAXN * MAXN + 2, MAXEG = 4 * MAXN * ( MAXN + 1 );
  31. int bound, ecnt, head[MAXND + 5], to[MAXEG + 5], nxt[MAXEG + 5];
  32. Value cst[MAXEG + 5], dist[MAXND + 5];
  33. inline void operator () ( const int s, const int t, const Value& c ) {
  34. #ifdef RYBY
  35. printf ( "%d %d (%lld,%lld)\n", s, t, c.w, c.e );
  36. #endif
  37. to[++ecnt] = t, cst[ecnt] = c, nxt[ecnt] = head[s];
  38. head[s] = ecnt;
  39. to[++ecnt] = s, cst[ecnt] = c, nxt[ecnt] = head[t];
  40. head[t] = ecnt;
  41. }
  42. inline Value dijkstra ( const int s, const int t ) {
  43. static bool vis[MAXND + 5];
  44. static std::priority_queue<PVI, std::vector<PVI>, std::greater<PVI> > heap;
  45. for ( int i = 1; i <= bound; ++i ) vis[i] = false, dist[i] = INF;
  46. heap.push ( { dist[s] = 0, s } );
  47. while ( !heap.empty () ) {
  48. PVI p ( heap.top () ); heap.pop ();
  49. if ( vis[p.second] ) continue;
  50. vis[p.second] = true;
  51. for ( int i = head[p.second], v; i; i = nxt[i] ) {
  52. if ( Value d ( p.first + cst[i] ); d < dist[v = to[i]] ) {
  53. heap.push ( { dist[v] = d, v } );
  54. }
  55. }
  56. }
  57. return dist[t];
  58. }
  59. } graph;
  60. inline int id ( const int i, const int j ) {
  61. if ( !i || j == n ) return S;
  62. if ( i == n || !j ) return T;
  63. return ( i - 1 ) * ( n - 1 ) + j;
  64. }
  65. inline Value calc ( const LL a, const LL b ) {
  66. coeW = a, coeE = b;
  67. Value ret ( graph.dijkstra ( S, T ) );
  68. #ifdef RYBY
  69. printf ( "calc(%lld,%lld) = (%lld,%lld)\n", a, b, ret.w, ret.e );
  70. #endif
  71. return graph.dijkstra ( S, T );
  72. }
  73. inline void solve ( const Value& A, const Value& B ) {
  74. LL a = A.e - B.e, b = B.w - A.w;
  75. Value C ( calc ( a, b ) );
  76. chkmin ( ans, C.w * C.e );
  77. #ifdef RYBY
  78. printf ( "(%lld,%lld), (%lld,%lld), (%lld,%lld)\n", A.w, A.e, C.w, C.e, B.w, B.e );
  79. printf ( "%lld...%lld\n", ( B - A ) * ( C - A ), a * C.w + b * C.e + A.w * B.e - A.e * B.w );
  80. #endif
  81. if ( ( B - A ) * ( C - A ) >= 0 ) return ;
  82. solve ( A, C ), solve ( C, B );
  83. }
  84. int main () {
  85. n = rint ();
  86. S = ( n - 1 ) * ( n - 1 ) + 1, T = S + 1;
  87. graph.bound = ( n - 1 ) * ( n - 1 ) + 2;
  88. for ( int i = 1; i < n; ++i ) {
  89. for ( int j = 1; j <= n; ++j ) {
  90. int cw = rint (), ce = rint ();
  91. graph ( id ( i, j - 1 ), id ( i, j ), { cw, ce } );
  92. }
  93. }
  94. for ( int i = 1; i <= n; ++i ) {
  95. for ( int j = 1; j < n; ++j ) {
  96. int rw = rint (), re = rint ();
  97. graph ( id ( i - 1, j ), id ( i, j ), { rw, re } );
  98. }
  99. }
  100. Value A ( calc ( 1, 0 ) ), B ( calc ( 0, 1 ) );
  101. chkmin ( ans, A.w * A.e ), chkmin ( ans, B.w * B.e );
  102. solve ( A, B );
  103. printf ( "%lld\n", ans );
  104. return 0;
  105. }

\(\mathcal{Details}\)

  虽然套路但毕竟是黑的,一眼秒掉好开心 owo。

Solution -「洛谷 P6158」封锁的更多相关文章

  1. Solution -「洛谷 P4372」Out of Sorts P

    \(\mathcal{Description}\)   OurOJ & 洛谷 P4372(几乎一致)   设计一个排序算法,设现在对 \(\{a_n\}\) 中 \([l,r]\) 内的元素排 ...

  2. Note/Solution -「洛谷 P5158」「模板」多项式快速插值

    \(\mathcal{Description}\)   Link.   给定 \(n\) 个点 \((x_i,y_i)\),求一个不超过 \(n-1\) 次的多项式 \(f(x)\),使得 \(f(x ...

  3. Solution -「洛谷 P4198」楼房重建

    \(\mathcal{Description}\)   Link.   给定点集 \(\{P_n\}\),\(P_i=(i,h_i)\),\(m\) 次修改,每次修改某个 \(h_i\),在每次修改后 ...

  4. Solution -「洛谷 P6577」「模板」二分图最大权完美匹配

    \(\mathcal{Description}\)   Link.   给定二分图 \(G=(V=X\cup Y,E)\),\(|X|=|Y|=n\),边 \((u,v)\in E\) 有权 \(w( ...

  5. Solution -「洛谷 P6021」洪水

    \(\mathcal{Description}\)   Link.   给定一棵 \(n\) 个点的带点权树,删除 \(u\) 点的代价是该点点权 \(a_u\).\(m\) 次操作: 修改单点点权. ...

  6. Solution -「洛谷 P4719」「模板」"动态 DP" & 动态树分治

    \(\mathcal{Description}\)   Link.   给定一棵 \(n\) 个结点的带权树,\(m\) 次单点点权修改,求出每次修改后的带权最大独立集.   \(n,m\le10^5 ...

  7. Solution -「洛谷 P5236」「模板」静态仙人掌

    \(\mathcal{Description}\)   Link.   给定一个 \(n\) 个点 \(m\) 条边的仙人掌,\(q\) 组询问两点最短路.   \(n,q\le10^4\),\(m\ ...

  8. Solution -「洛谷 P4320」道路相遇

    \(\mathcal{Description}\)   Link.   给定一个 \(n\) 个点 \(m\) 条边的连通无向图,并给出 \(q\) 个点对 \((u,v)\),询问 \(u\) 到 ...

  9. Solution -「洛谷 P5827」边双连通图计数

    \(\mathcal{Description}\)   link.   求包含 \(n\) 个点的边双连通图的个数.   \(n\le10^5\). \(\mathcal{Solution}\)    ...

随机推荐

  1. Java 简单操作hdfs API

    注:图片如果损坏,点击文章链接:https://www.toutiao.com/i6632047118376780295/ 启动Hadoop出现问题:datanode的clusterID 和 name ...

  2. js复制文本到剪贴板

    execCommand是document的一个方法,返回值是布尔值(true,false) true表示操作被支持,false表示操作不被支持 此方法只针对于input和textarea,对里面的内容 ...

  3. springBoot--01--快速入门

    笔记源码:https://gitee.com/ytfsL/springboot 1.1 原有Spring优缺点分析 1.1.1 Spring的优点分析 Spring是Java企业版(Java Ente ...

  4. Zookeeper绍二(分布式锁介)

    一.为什么会有分布式锁? 在多线程环境下,由于上下文的切换,数据可能出现不一致的情况或者数据被污染,我们需要保证数据安全,所以想到了加锁. 所谓的加锁机制呢,就是当一个线程访问该类的某个数据时,进行保 ...

  5. 1月29日 体温APP开发记录

    1.阅读构建之法 现代软件工程(第三版) 2.观看Android开发视频教程最新版 Android Studio开发 3.高德地图API下载获取key  

  6. 2022GDUT寒训专题一C题

    题目 题面 马在中国象棋以日字形规则移动. 请编写一段程序,给定n×m大小的棋盘,以及马的初始位置 (x, y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点. 输入格式 ...

  7. QT之鼠标事件

    Widget.h: #ifndef WIDGET_H #define WIDGET_H #include<QWidget> #include<QMouseEvent> clas ...

  8. 使用ansible 批量分发ssh密钥

    先看执行结果 看看ssh.yml怎么写的 看看hosts文件中backup组怎么写的

  9. 好用的 NPL 词库分类。

    ## 好用的 NPL 词库分类. 专业的词库分类技术. 主要服务于金融领域的词库划分. 上图!对比一下我们的分词和jie等模型的效果.做的就是专业! ![在这里插入图片描述](https://img- ...

  10. QA(测试) 工作准则建议

    身为一个专业的 QA 当然需要有自己的测试原则,这些测试原则不仅可以帮助我们提高产品质量,对外还能体现出我们的专业性,从而让合作方后续还有意愿和我们合作. 1 测试前 1.1 需求评审 必须参与,有问 ...