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. XML的语法

    XML的语法 文档声明: 写法 <?xml version="1.0" ?> 文档声明必须出现在xml文件的第一行和第一列的位置 属性: version="1 ...

  2. UVA 10417 Gift Exchanging

    #include <iostream> #include <cstring> #include <stdio.h> #include <math.h> ...

  3. LeetCode LFU Cache

    原题链接在这里:https://leetcode.com/problems/lfu-cache/?tab=Description 题目: Design and implement a data str ...

  4. vue-router导航守卫

    导航守卫 译者注 “导航”表示路由正在发生改变. 正如其名,vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航.有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件 ...

  5. bzoj 3907 网格 bzoj2822 [AHOI2012]树屋阶梯——卡特兰数(阶乘高精度模板)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3907 https://www.lydsy.com/JudgeOnline/problem.p ...

  6. HDU4825(字典树+贪心)

    Xor Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)Total S ...

  7. hibernate中mysql数据交互中文乱码问题

    来源于"http://www.cnblogs.com/jiafuwei/p/4423101.html"; 修改hibernate的配置文件hibernate.cfg.xml,在配置 ...

  8. 一些js和JQuery的方法

    取值填值: js: get-- innerText, innerHTML, value;  set-- innerText=?, innerHTML=?, value=?; JQuery: get-- ...

  9. ARRINC424—MORA(GRID)格式

    每一整数经.纬度为一格,每格MORA值3位数字,表示百英尺.无法获知MORA值得网格一UNK表示. 经纬网格起始点坐标,每个网格从左下角开始计数,每经纬度一度切分一个网格.每行数据代表某一维度上往东或 ...

  10. CSS3 高级属性

    尽管现代浏览器已经支持了众多的CSS3属性,但是大部分设计师和开发人员貌似依然在关注于一些很“主流”的属性,如border-radius.box-shadow或者transform等.它们有良好的文档 ...