BZOJ 1001……

并不会这个trick,所以笔记要详细一点。

前置知识 : 平面图转对偶图    传送门

听说直接$Dinic$就好了,还跑得比正解快……

首先我们按照平面图的定义,把网格图中所有的平面以及另加的起点和终点在新图中标号,一共有$(n - 1) * (m - 1) * 2 + 2$个点,标完样例之后大概是这样子的:

然后我们接着按照定义,把有相邻的边的点连上双向边,对于那些在边界上的边,我们分别选择和$st$和$ed$连边,具体来说是这样的:

红色的边和$st$连边,蓝色的边和$ed$连边,其他黑色的边和它相邻的两个联通块连边。

注意$n == 1$或者$m == 1$的时候其实是一条链的情况,只要把最小的边鸽掉就好了,这时候所有的边都是要从$st$出发连到$ed$的,但是我的写法会挂掉,所以需要拎出来特判一下。

容易发现这样子构图之后从$st$到$ed$的每一条路都对应了原图中左上角到右下角的一个鸽,这样子我们求一个最小鸽就变成了一个最短路,就能方便地跑过去了。

要注意一个细节就是说$st$和$ed$必须放在左下角和右上角(可以对调),因为我们在原图中是要从左上角到右下角求一个最小鸽,要不然就不代表从左上角到右下角的一个最小鸽了吧。

连完边之后的效果图大概是这个大神博客里面的样子。    戳这里

时间复杂度$O(nmlognm)$。

Code:

#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
using namespace std;
typedef pair <int, int> pin; const int N = 2e6 + ;
const int M = 6e6 + ; int n, m, tot = , head[N], dis[N];
bool vis[N]; struct Edge {
int to, nxt, val;
} e[M]; inline void add(int from, int to, int val) {
e[++tot].to = to;
e[tot].val = val;
e[tot].nxt = head[from];
head[from] = tot;
} inline void addEdge(int x, int y, int v) {
add(x, y, v), add(y, x, v);
} inline void read(int &X) {
X = ; char ch = ; int op = ;
for(; ch > '' || ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} priority_queue <pin> Q;
inline void dij(int st) {
memset(dis, 0x3f, sizeof(dis));
memset(vis, , sizeof(vis));
Q.push(pin(dis[st] = , st));
for(; !Q.empty(); ) {
int x = Q.top().second; Q.pop();
if(vis[x]) continue;
vis[x] = ;
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(dis[y] > dis[x] + e[i].val) {
dis[y] = dis[x] + e[i].val;
Q.push(pin(-dis[y], y));
}
}
}
} int main() {
// freopen("5.in", "r", stdin); read(n), read(m);
int st = (n - ) * (m - ) * + , ed = st + ;
if(n == || m == ) {
for(int i = ; i <= n; i++)
for(int j = ; j < m; j++) {
int val; read(val);
addEdge(st, ed, val);
}
for(int i = ; i < n; i++)
for(int j = ; j <= m; j++) {
int val; read(val);
addEdge(st, ed, val);
}
for(int i = ; i < n; i++)
for(int j = ; j < m; j++) {
int val; read(val);
addEdge(st, ed, val);
}
} else {
for(int i = ; i <= n; i++)
for(int j = ; j < m; j++) {
int val; read(val);
if(i == ) addEdge(ed, * ((i - ) * (m - ) + j), val);
if(i == n) addEdge(st, * ((i - ) * (m - ) + j) - , val);
if(i != && i != n) addEdge( * ((i - ) * (m - ) + j), * ((i - ) * (m - ) + j) - , val);
}
for(int i = ; i < n; i++)
for(int j = ; j <= m; j++) {
int val; read(val);
if(j == ) addEdge(st, * ((i - ) * (m - ) + j) - , val);
if(j == m) addEdge(ed, * ((i - ) * (m - ) + j - ), val);
if(j != && j != m) addEdge( * ((i - ) * (m - ) + j) - , * ((i - ) * (m - ) + j) - , val);
}
for(int i = ; i < n; i++)
for(int j = ; j < m; j++) {
int val; read(val);
addEdge( * ((i - ) * (m - ) + j) - , * ((i - ) * (m - ) + j), val);
}
} dij(st); printf("%d\n", dis[ed]);
return ;
}

Luogu 4001 [BJOI2006]狼抓兔子的更多相关文章

  1. BZOJ1001 洛谷4001 [BJOI2006]狼抓兔子 题解

    题目 这个题目有多种解法,这个题也是一个比较经典的题了,正是因为他的多样的做法,这个题主要难在建图和优化,因为这是一个网格图,所以spfa肯定过不去,所以用最短路解法的话,只能用dij,而网络流也是要 ...

  2. BZOJ1001或洛谷4001 [BJOI2006]狼抓兔子

    BZOJ原题链接 洛谷原题链接 显然就是求最小割. 而对于一个平面图有结论,最大流=最小割=对偶图最短路. 所以这题可用最大流或是转换为对偶图求最短路,这里我是用的对偶图. 虽然理论上按上界算,这题\ ...

  3. P4001 [BJOI2006]狼抓兔子(对偶图)

    P4001 [BJOI2006]狼抓兔子 最短路+对偶图 看这题最容易想到的就是网络流.Dinic可以过,据说还跑得比正解快. 如果不写网络流,那么需要知道2个前置知识:平面图和对偶图(右转baidu ...

  4. BJOI2006狼抓兔子

    1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 9967  Solved: 2267[Submit][S ...

  5. 752. [BJOI2006] 狼抓兔子

    ★★★   输入文件:bjrabbit.in   输出文件:bjrabbit.out   简单对比时间限制:1 s   内存限制:162 MB Description   Source: Beijin ...

  6. [BJOI2006]狼抓兔子

    题目描述 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: ...

  7. 1001. [BJOI2006]狼抓兔子【最小割】

    Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一 ...

  8. BZOJ1001 BJOI2006 狼抓兔子

    Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个 ...

  9. [BJOI2006]狼抓兔子(网络流)

    题目描述 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: ...

随机推荐

  1. Shell编程-运算符

    1.declare命令 declare声明变量类型:declare [+/-][选项] 变量名 -:给变量设定类型属性 +:取消变量的类型属性 -a:将变量声明为数组型 -i:整数型 -x:环境变量 ...

  2. 《深入理解 C# 第2版》 - 书摘精要

    (P13) 在很大程度上,C# 2 更像是对 C# 1 的各种不足之处的修修补补,所以并没有一鸣惊人.而 C# 3 中几乎所有特性都是为了构建 LINQ,并且其结果也十分特别: (P24) 为了让委托 ...

  3. 2017 年比较 Angular、React、Vue 三剑客(转载)

    为 web 应用选择 JavaScript 开发框架是一件很费脑筋的事.现如今 Angular 和 React 非常流行,并且最近出现的新贵 VueJS 同样博得了很多人的关注.更重要的是,这只是一些 ...

  4. Android Studio 学习 - Activity生命周期

    落下两晚了,继续学习…… 先粘贴2张官方给的流程图: ------------------------------------------------------------------------- ...

  5. 我的 Linux 配置

    系统版本 Ubuntu 18.04 一名老年弱智 OI 选手的 Linux 配置 文本编辑器: Sublime Text 中文补丁,关闭自动补全,自动联想,括号匹配,字号 15 编译器: g++ (然 ...

  6. 【LeetCode】007. Reverse Integer

    Given a 32-bit signed integer, reverse digits of an integer. Example 1: Input: 123 Output: 321 Examp ...

  7. 使用.NET中的XML注释(一) -- XML注释标签讲解

    一.摘要 .Net允许开发人员在源代码中插入XML注释,这在多人协作开发的时候显得特别有用. C#解析器可以把代码文件中的这些XML标记提取出来,并作进一步的处理为外部文档. 这篇文章将展示如何使用这 ...

  8. 推荐几本学习MySQL的好书

    转载:http://mingxinglai.com/cn/2015/12/material-of-mysql/ 我这里推荐几本MySQL的好书,应该能够有效避免学习MySQL的弯路,并且达到一个不错的 ...

  9. 洛谷【P1886】滑动窗口

    浅谈队列:https://www.cnblogs.com/AKMer/p/10314965.html 题目传送门:https://www.luogu.org/problemnew/show/P1886 ...

  10. LdapContext获取对象的属性

    //            dn = "cn=1,cn=Users,DC=域名,DC=COM";//            Attributes answer = ctx.getA ...