BZOJ1001 狼抓兔子(网络流转最短路:对偶图)
题意:
给一个如图形式的\(n*m\)的方格,从左上走到右下,给出边权,问分成两块所需的最小代价。\(n,m\leq1000\)。
思路:
显然是个最小割,但是\(O(n^2m)\)的复杂度很高,虽然这道题能过。
这里介绍一种最大流改最短路的方法——对偶图。
对任意一个图我们可以变成对偶图:
如下图,每一个闭合的平面我们都给他标号,然后连接源点和汇点,把外面那个无穷大的平面分成两个平面\(s,t\)。然后开始新建边。新建边的每一条边为:把一条原来边的左右两个平面连接到一起,权值为原来的边的权值。可以得出最后的新建的边的数量和原来一样。最后跑\(s,t\)的最短路即可得出原图的最大流。

代码:
#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <stack>
#include <ctime>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int maxn = 3e6 + 5;
const int MAXM = 3e6;
const ll MOD = 1e9 + 7;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
struct Edge{
int to, next;
int w;
}edge[MAXM * 2];
struct qnode{
int u;
int c;
qnode(int _u = 0, int _c = 0):u(_u), c(_c){}
bool operator < (const qnode &r) const{
return r.c < c;
}
};
int tot, head[maxn], vis[maxn];
int dis[maxn];
void addEdge(int u, int v, int w){
edge[tot].to = v;
edge[tot].w = w;
edge[tot].next = head[u];
head[u] = tot++;
}
void Dijkstra(int n, int st){
memset(vis, 0, sizeof(vis));
for(int i = 0; i <= n; i++) dis[i] = INF;
priority_queue<qnode> que;
while(!que.empty()) que.pop();
dis[st] = 0;
que.push(qnode(st, 0));
qnode temp;
while(!que.empty()){
temp = que.top();
que.pop();
int u = temp.u;
if(vis[u]) continue;
vis[u] = 1;
for(int i = head[u]; i != -1; i = edge[i].next){
int v = edge[i].to;
int w = edge[i].w;
if(!vis[v] && dis[v] > dis[u] + w){
dis[v] = dis[u] + w;
que.push(qnode(v, dis[v]));
}
}
}
}
int n, m;
int getupid(int x, int y){
return (x - 1) * (m - 1) + y;
}
int getdownid(int x, int y){
return (x - 1) * (m - 1) + y + (n - 1) * (m - 1);
}
int main(){
memset(head, -1, sizeof(head));
tot = 0;
scanf("%d%d", &n, &m);
if(n == 1 || m == 1){
int ans = INF;
if(n == m) ans = 0;
if(n < m) swap(n, m);
for(int i = 1; i <= n - 1; i++){
int w;
scanf("%d", &w);
ans = min(ans, w);
}
printf("%d\n", ans);
return 0;
}
int st = 0, en = (n - 1) * (m - 1) * 2 + 1;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m - 1; j++){
int w;
scanf("%d", &w);
if(i == 1){
addEdge(st, getupid(i, j), w);
addEdge(getupid(i, j), st, w);
}
else if(i == n){
addEdge(en, getdownid(i - 1, j), w);
addEdge(getdownid(i - 1, j), en, w);
}
else{
addEdge(getupid(i, j), getdownid(i - 1, j), w);
addEdge(getdownid(i - 1, j), getupid(i, j), w);
}
}
}
for(int i = 1; i <= n - 1; i++){
for(int j = 1; j <= m; j++){
int w;
scanf("%d", &w);
if(j == 1){
addEdge(getdownid(i, j), en, w);
addEdge(en, getdownid(i, j), w);
}
else if(j == m){
addEdge(getupid(i, j - 1), st, w);
addEdge(st, getupid(i, j - 1), w);
}
else{
addEdge(getdownid(i, j), getupid(i, j - 1), w);
addEdge(getupid(i, j - 1), getdownid(i, j), w);
}
}
}
for(int i = 1; i <= n - 1; i++){
for(int j = 1; j <= m - 1; j++){
int w;
scanf("%d", &w);
addEdge(getupid(i, j), getdownid(i, j), w);
addEdge(getdownid(i, j), getupid(i, j), w);
}
}
Dijkstra(en, st);
printf("%d\n", dis[en]);
return 0;
}
BZOJ1001 狼抓兔子(网络流转最短路:对偶图)的更多相关文章
- [bzoj1001][BJOI2006]狼抓兔子——最大流转最短路,平面图
题目描述: 给定一个平面图,求最小割. 题解: 本题是一道经典题. 周冬Orz的论文是很好的研究资料. 这道题点太多,所以直接跑dinic无疑会超时. 我们观察原图,发现原图是一个平面图. 什么是平面 ...
- bzoj1001狼抓兔子 对偶图优化
bzoj1001狼抓兔子 对偶图优化 链接 https://www.lydsy.com/JudgeOnline/problem.php?id=1001 思路 菜鸡总是要填坑的! 很明显让你求网格图的最 ...
- BZOJ-1001 狼抓兔子 (最小割-最大流)平面图转对偶图+SPFA
1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec Memory Limit: 162 MB Submit: 14686 Solved: 3513 [Submit][ ...
- bzoj1001狼抓兔子
1001: [BeiJing2006]狼抓兔子 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨,它们只有两个窝,现在你 ...
- BZOJ1001:狼抓兔子(最小割最大流+vector模板)
1001: [BeiJing2006]狼抓兔子 Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨, ...
- 【BZOJ】1001: [BeiJing2006]狼抓兔子 Dinic算法求解平面图对偶图-最小割
1001: [BeiJing2006]狼抓兔子 Description 左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下 三种类型的道路 1:(x,y)<==>( ...
- BZOJ_2001_[BeiJing2006]狼抓兔子_最小割转对偶图
BZOJ_2001_[BeiJing2006]狼抓兔子 题意:http://www.lydsy.com/JudgeOnline/problem.php?id=1001 分析:思路同NOI2010海拔. ...
- 【建图+最短路】Bzoj1001 狼抓兔子
Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个 ...
- BZOJ1001 狼抓兔子(裸网络流)
Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一 ...
- BZOJ1001 狼抓兔子 平面图转对偶图 最小割
现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: 左上角点为 ...
随机推荐
- Java程序入门
编写Java源程序 在d:\day01 目录下新建文本文件,完整的文件名修改为HelloWorld.java ,其中文件名为HelloWorld ,后缀名必须为.java . 用记事本打开 在文件中键 ...
- Java基础复习2
三目运算符 语法:条件判断?表达式1:表达式2; 如果条件判断成立则获取值1否则获取值2 public class demo1{ public static void main(String[ ...
- Django-初阶实例
调用本地css文件的方法 setting.py里面的内容 import os # Build paths inside the project like this: os.path.join(BASE ...
- ElasticSearch-IK分词器和集成使用
1.查询存在问题分析 在进行字符串查询时,我们发现去搜索"搜索服务器"和"钢索"都可以搜索到数据: 而在进行词条查询时,我们搜索"搜索"却没 ...
- 拓扑排序(topo sort)之 最大食物链计数( 洛谷P4017)
前言: 复习复习拓扑排序,自己把自己弄没了/kk 题目传送门 简化题意: 在一个DAG中,求从所有入度为0的点到所有出度为0的点路径的条数 md理解错题意把自己卡了半天,生物学的好的就可以直接理解为求 ...
- Language Guide (proto3) | proto3 语言指南(十二)定义服务
Defining Services - 定义服务 如果要在RPC(Remote Procedure Call,远程过程调用)系统中使用消息类型,可以在.proto文件中定义RPC服务接口,协议缓冲区编 ...
- 最短路-Bellmm-ford算法
Bellmm-ford算法 解决什么样的问题 有边数限制的最短路,存在负权边,负环 概念 通俗的来讲就是:假设 1 号点到 n 号点是可达的,每一个点同时向指向的方向出发,更新相邻的点的最短距离,通过 ...
- Web漏洞扫描-Burp Suite
Web漏洞扫描-Burp Suite 一.Burp Suite概述 二.功能及特点 三.Burp Suite安装 四.Burp Suite使用 一.Burp Suite概述 安全渗透界使用最广泛的漏扫 ...
- Scala-文件操作
Scala-文件操作 一.遍历一个文件中的每一行 方法一: 使用Source.getLines返回的迭代器 方法二: 将Source.getLines返回的迭代器,转换成数组 方法三: 调用Sourc ...
- JavaWeb——Ajax与MVC学习总结
Ajax: 什么是Ajax? 为什么使用Ajax? 使用jquery Ajax实现登录 Ajax实例练习: 设计模式 设计模式的定义: 设计模式的作用: MVC设计模式 MVC设计模式的模块组成: M ...