拖了将近5天的正解和AC.........emmmmm...........

事实告诉我们这种毒瘤题一定要建双向边(用了不知道多少个小时质疑建边的人欲哭无泪)

心态爆炸的传送

题了个面

这是个求最小割问题

说人话:

把图中的一些边砍断,使这个图分为不连通的两部分。砍断一条边的代价就是这条边的边权,求最小代价。

似乎是个定理的东西:

一个图的最小割是对偶图的最短路

question1:神马是对偶图?能吃吗?

当然不能

在这里的对偶图,就是把原来的块当做点,把原来的边建成与之垂直的边,边权不变,再在左下角和右上角新建两个点st,eend(这两个点放在哪个角上无所谓辣),作为源点和汇点,跑最短路。

为毛是eend而不是end呢?

因为在c++11下end会CE

说的太抽象了,举个例子

原图:

对偶图:

思路很简单,but代码还是很难(它是个要面子的题)

我们想想怎么给这些点编号

(其实随便编号)

窝的编号方法:

接下来我们分边讨论怎么表示点(注意一定要建双向边)

横边:

左边的红字是边的行号 i ,上边的是边的列号 j

我们要计算每条边(i,j)上面的点和下面的点,如果边的行号是1,则直接向终点eend建边,如果边的行号是 n ,就向起点st建边,否则,上下建边(注意建双向边*2)

点的表示方法:

上面的点 ss=2*(i-1)*(m-1)+j+1;

下面的点 ee=ss-m+1;

竖边:

右边的点:ss=j+(m-1)*(2*(i-1)+1)+1;

左边的点:ee=ss-m;

当j=1时:st与右边的点连边

当j=m时:左边的点与eend连边

正常情况:左边的点与右边的点连边

注意建双向边!!!(*3)

斜边:

斜上方的点:ss=2*(i-1)*(m-1)+j+1;

斜下方的点:ee=ss+m-1;

这里就不需要考虑st和eend了

双向建边*5

建完边之后跑一遍dijkstra就好辣

Code:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#include<algorithm>
#define ll long long
#define pa pair<int,int>
using namespace std;
inline int read()
{
char ch=getchar(),lst;
int x=;
while(ch<''||ch>'')
{
lst=ch;
ch=getchar();
}
while(ch>=''&&ch<='')
{
x=(x<<)+(x<<)+(ch^);
ch=getchar();
}return ((lst=='-')?-x:x);
}
int n,m,st=,eend,head[],cnt,dis[];
const int inf=;
bool vis[];
struct Ed{
int to,nxt,dis;
}edge[];
void add(int fr,int to,int dis)
{
cnt++;
edge[cnt].to=to;
edge[cnt].dis=dis;
edge[cnt].nxt=head[fr];
head[fr]=cnt;
}
void dij()//堆优化的dij
{
for(int i=;i<=eend;i++)
dis[i]=inf;
dis[]=;
priority_queue<pa,vector<pa>,greater<pa> > q;
q.push(make_pair(,));
while(!q.empty())
{
int now=q.top().second;
q.pop();
if(vis[now])continue;
vis[now]=;
for(int e=head[now];e;e=edge[e].nxt)
{
int v=edge[e].to,di=edge[e].dis;
if(dis[now]+di<dis[v])
{
dis[v]=dis[now]+di;
q.push(make_pair(dis[v],v));
}
}
}
}
int main()
{
n=read();m=read();
eend=(n-)**(m-)+;
for(int i=;i<=n;i++)//横边
{
for(int j=;j<=m-;j++)
{
int dis=read();
int ss=*(i-)*(m-)+j+;
int ee=ss-m+;
if(i==)
{add(ss,eend,dis);add(eend,ss,dis);
continue;}
if(i==n)
{add(st,ee,dis);add(ee,st,dis);
continue;}
add(ss,ee,dis);add(ee,ss,dis);
}
}//竖边
for(int i=;i<n;i++)
{
for(int j=;j<=m;j++)
{
int dis=read();
int ss=j+(m-)*(*(i-)+)+;
int ee=ss-m;
if(j==)
{add(st,ss,dis);add(ss,st,dis);
continue;}
if(j==m)
{add(ee,eend,dis);add(eend,ee,dis);
continue;}
add(ee,ss,dis);add(ss,ee,dis);
}
}//斜边
for(int i=;i<n;i++)
{
for(int j=;j<m;j++)
{
int dis=read();
int ss=*(i-)*(m-)+j+;
int ee=ss+m-;
add(ee,ss,dis);
add(ss,ee,dis);
}
}
dij();
printf("%d",dis[eend]);
}

duliu题之狼抓兔子题解的更多相关文章

  1. 【bzoj1001】【最短路】【对偶图】【最大流转最小割】狼抓兔子题解

    [BZOJ1001]狼抓兔子 1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 18872  Solved ...

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

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

  3. BZOJ1001 狼抓兔子 题解

    裸的最小割,转化成最大流即可. #include <bits/stdc++.h> int n,m; int S,T; int mincost; int head[6001000],tot= ...

  4. 【BZOJ1001】狼抓兔子

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

  5. 【BZOJ1001】狼抓兔子(网络流)

    [BZOJ1001]狼抓兔子(网络流) 题面 Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨, ...

  6. BZOJ1001: [BeiJing2006]狼抓兔子【最短路+对偶图】

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1001 1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Se ...

  7. 【BZOJ1001】狼抓兔子(平面图转对偶图,最短路)

    [BZOJ1001]狼抓兔子(平面图转对偶图,最短路) 题面 BZOJ 洛谷 题解 这题用最小割可以直接做 今天再学习了一下平面图转对偶图的做法 大致的思路如下: 1.将源点到汇点中再补一条不与任何线 ...

  8. BZOJ1001:狼抓兔子(最小割最大流+vector模板)

    1001: [BeiJing2006]狼抓兔子 Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨, ...

  9. bzoj1001: [BeiJing2006]狼抓兔子(初识是你最小割)

    1001: [BeiJing2006]狼抓兔子 题目:传送门 题解: 听说这题当初是大难题...可惜当年没有网络流hahahha 现在用网络流的思想就很容易解决了嘛 给什么连什么,注意是双向边,然后跑 ...

随机推荐

  1. 19: vue项目使用整理

    1.1  axios 基本用法 安装:npm install axios -S                   # 也可直接下载axios.min.js文件 1.axios借助Qs对提交数据进行序 ...

  2. MySQL 的自增 ID 用完了,怎么办?

      一.简述 在 MySQL 中用很多类型的自增 ID,每个自增 ID 都设置了初始值.一般情况下初始值都是从 0 开始,然后按照一定的步长增加.在 MySQL 中只要定义了这个数的字节长度,那么就会 ...

  3. 制作的第一个java小游戏

    package java1; import java.awt.*; public class java1 extends Frame { //球桌和桌球图片 Image ball = Toolkit. ...

  4. Android模拟器运行慢的解决方案

    在android开发的过程,发现android模拟器的速度不是一般的慢,那主要是因为android模拟器默认采用的是arm处理器造成的,这里主要提供两种方法: ① 利用intel虚拟硬件加速的方式,实 ...

  5. mvvm实现一个简单的vue

    vue,基于mvvm模式下的一个前端框架 mvvm模式下简单的实现数据代理,数据劫持 1.是用Object.defineProperty 实现数据代理 2.使用发布订阅者模式,配合 Object.de ...

  6. js函数调用的几种方法

    js的函数调用会免费奉送两个而外的参数就是 this 和 arguments .arguments是参数组,他并不是一个真实的数组,但是可以使用.length方法获得长度. 书上有说4中调用方式: 方 ...

  7. linux系统下如何在vscode中调试C++代码

    本篇博客以一个简单的hello world程序,介绍在vscode中调试C++代码的配置过程. 1. 安装编译器 vscode是一个轻量的代码编辑器,并不具备代码编译功能,代码编译需要交给编译器完成. ...

  8. Cobbler自动化装机

    Cobbler自动化装机 一个可以实现批量安装系统的Linxu应用程序,他可以实现同个服务器安装不同操作系统版本. 准备环境 开启两个网卡.一个仅主机模式,一个桥接模式,仅主机模式对内提供cobble ...

  9. /proc/sys/fs/file-max

    Linux的/proc/sys/fs/file-max决定了当前内核可以打开的最大的文件句柄数. 查看当前的值: cat /proc/sys/fs/file-max 这个值在kernel的文档里是这样 ...

  10. PAT Basic 1032 挖掘机技术哪家强 (20 分)

    为了用事实说明挖掘机技术到底哪家强,PAT 组织了一场挖掘机技能大赛.现请你根据比赛结果统计出技术最强的那个学校. 输入格式: 输入在第 1 行给出不超过 1 的正整数 N,即参赛人数.随后 N 行, ...