BZOJ原题链接

洛谷原题链接

显然就是求最小割。

而对于一个平面图有结论,最大流=最小割=对偶图最短路。

所以这题可用最大流或是转换为对偶图求最短路,这里我是用的对偶图。

虽然理论上按上界算,这题\(Dinic\)应该是跑不过去的,不过因为网络流复杂度玄学,\(Dinic\)莫名跑得挺快的。

在转换对偶图的时候,注意\(n = 1\)或\(m = 1\)的情况。

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N = 2e6 + 10;
const int M = 7e6 + 10;
struct po {
int x, d;
bool operator < (const po &b) const
{
return d > b.d;
}
};
po X;
int fi[N], di[M], ne[M], da[M], dis[N], l, st, ed, n, m;
bool v[N];
priority_queue<po>q;
inline int re()
{
int x = 0;
char c = getchar();
bool p = 0;
for (; c < '0' || c > '9'; c = getchar())
p |= c == '-';
for (; c >= '0' && c <= '9'; c = getchar())
x = x * 10 + c - '0';
return p ? -x : x;
}
inline void add(int x, int y, int z)
{
di[++l] = y;
da[l] = z;
ne[l] = fi[x];
fi[x] = l;
di[++l] = x;
da[l] = z;
ne[l] = fi[y];
fi[y] = l;
}
inline int ch(int x, int y, int L)
{
int k = ((x - 1) * (m - 1) + y) << 1;
return L ? k - 1 : k;
}
inline void add_row(int x, int y, int z)
{
if (!(x ^ 1))
add(ch(x, y, 0), ed, z);
else
if (!(x ^ n))
add(st, ch(x - 1, y, 1), z);
else
add(ch(x - 1, y, 1), ch(x, y, 0), z);
}
inline void add_col(int x, int y, int z)
{
if (!(y ^ 1))
add(st, ch(x, y, 1), z);
else
if (!(y ^ m))
add(ch(x, y - 1, 0), ed, z);
else
add(ch(x, y - 1, 0), ch(x, y, 1), z);
}
inline void add_opl(int x, int y, int z)
{
add(ch(x, y, 1), ch(x, y, 0), z);
}
int main()
{
int i, j, x, y;
n = re();
m = re();
st = (n - 1) * (m - 1) << 1 | 1;
ed = st + 1;
if (!(n ^ 1) || !(m ^ 1))
{
for (i = 1; i <= n; i++)
for (j = 1; j < m; j++)
add(st, ed, re());
for (i = 1; i < n; i++)
for (j = 1; j <= m; j++)
add(st, ed, re());
for (i = 1; i < n; i++)
for (j = 1; j < m; j++)
add(st, ed, re());
}
else
{
for (i = 1; i <= n; i++)
for (j = 1; j < m; j++)
add_row(i, j, re());
for (i = 1; i < n; i++)
for (j = 1; j <= m; j++)
add_col(i, j, re());
for (i = 1; i < n; i++)
for (j = 1; j < m; j++)
add_opl(i, j, re());
}
memset(dis, 60, sizeof(dis));
X.d = dis[X.x = st] = 0;
q.push(X);
while (!q.empty())
{
x = q.top().x;
q.pop();
if (v[x])
continue;
v[x] = 1;
for (i = fi[x]; i; i = ne[i])
if (dis[X.x = y = di[i]] > dis[x] + da[i])
{
X.d = dis[y] = dis[x] + da[i];
q.push(X);
}
}
printf("%d", dis[ed]);
return 0;
}

最新文章

  1. kindEditor完整认识 PHP上调用并上传图片说明/////////////////////////////z
  2. Thrift架构~动态Thrift插件的注入
  3. LINGO使用教程(一)
  4. Linux系统文件访问控制列表
  5. C语言之宏
  6. LINUX CACHE IO THREAD
  7. Error, some other host already uses address
  8. hibernate sql查询转换成VO返回list
  9. JavaScript 知识图谱
  10. C++ 重点关键字
  11. monkey测试 -- 原理和操作步骤
  12. mac上adb command not found
  13. 【Java】 剑指offer(35) 复杂链表的复制
  14. ANTLR#1:描述一个简单计算器
  15. Segment Advisor
  16. U盘安装centos7:不能载入到安装界面
  17. python3+pyzbar+Image 进行图片二维码识别
  18. jni里找不到刚添加的C++函数
  19. C#根据URL生成签名
  20. js常用代码记录

热门文章

  1. 学JS的心路历程 - JS的Class
  2. beta分布 java代码
  3. hdu1215-七夕节-(埃氏筛+唯一分解定理)
  4. SAP 优缺点
  5. MD5 算法
  6. css-background-image 背景图片太大或太小
  7. 第五篇:jmeter图形监控扩展
  8. js 中的原型链与继承
  9. cf-Global Round2-C. Ramesses and Corner Inversion(思维)
  10. 优化-最小化损失函数的三种主要方法:梯度下降(BGD)、随机梯度下降(SGD)、mini-batch SGD