【解题思路】

  显然,这题的答案是这个网格图的最小割。根据最大流-最小割定理,我们可以用网络流算法来求其最小割,时间复杂度最小为O(V2√E)。

  特殊的,这个网格图是一个平面图,于是可以根据平面图最小割-最短路定理,转化为其对偶图的最短路,时间复杂度最小为O(kE)或O(Vlog2V)(民科算法spfa前途不可估量)。

【参考代码】

  恩,听说这题我当初RE得生活不能自理,于是直接贴了orz::hzwer大神的代码。。

  贴个T掉的SAP板子。。(已修正了假板子的当前弧优化。。但还是T得生活不能自理。。)

 #pragma GCC optimize(2)
#include <algorithm>
#include <cstring>
#include <functional>
#define REP(i,low,high) for(register int i=(low);i<=(high);++i)
#define INF (0x7f7f7f7f)
#define function(type) __attribute__((optimize("-O2"))) inline type
#define procedure __attribute__((optimize("-O2"))) inline void
using namespace std; //ex_cmp {
template<typename T,class Compare>
inline bool getcmp(T&target,const T&pattern,Compare comp)
{
return comp(pattern,target)?target=pattern,:;
}
//} ex_cmp //quick_io {
#include <cctype>
#include <cstdio>
function(int) getint()
{
char c=getchar(); for(;!isdigit(c)&&c!='-';c=getchar());
short s=; for(;c=='-';c=getchar()) s*=-; int r=;
for(;isdigit(c);c=getchar()) r=(r<<)+(r<<)+c-'';
return s*r;
}
//} quick_io static const int N=,M=; static int cardE=; struct edge
{
int fr,to,cap;
edge(const int&f=,const int&t=,const int&c=)
:fr(f),to(t),cap(c) {}
}edg[(M<<)+]; int hed[N+],nxt[(M<<)+],hsh[][]; procedure add_edge(const int&fr,const int&to,const int&cp)
{
edg[cardE]=edge(fr,to,cp),nxt[cardE]=hed[fr],hed[fr]=cardE++;
} //SAP {
int aug[N+],cur[N+],dis[N+],gap[N+],path[N+]; function(int) augment(const int&S,const int&T)
{
for(register int i=T;i!=S;i=edg[path[i]].fr)
{
edg[path[i]].cap-=aug[T],edg[path[i]^].cap+=aug[T];
}
return aug[T];
} function(int) SAP(const int&S,const int&T,const int&N)
{
memset(aug,,sizeof aug),memset(gap,,sizeof gap);
memset(dis,,sizeof dis); REP(i,,N) cur[i]=hed[i];
aug[S]=INF,gap[]=N; int ret=;
for(register int fr=S;dis[S]<N;)
{
if(fr==T) ret+=augment(fr=S,T); bool flag=;
for(register int i=cur[fr];~i;i=nxt[i])
{
int to=edg[i].to;
if(edg[i].cap&&dis[fr]==dis[to]+)
{
aug[to]=min(aug[fr],edg[i].cap)
,path[to]=cur[fr]=i,fr=to,flag=; break;
}
}
if(flag)
{
if(!--gap[dis[fr]]) break; dis[fr]=N;
for(register int i=hed[fr];~i;i=nxt[i])
if(edg[i].cap)
{
getcmp(dis[fr],dis[edg[i].to]+,less<int>());
}
++gap[dis[fr]],cur[fr]=hed[fr];
if(fr!=S) fr=edg[path[fr]].fr;
}
}
return ret;
}
//} SAP int main()
{
int n=getint(),m=getint(),cardP=;
REP(i,,n) REP(j,,m) hsh[i][j]=++cardP;
memset(hed,-,sizeof hed),memset(nxt,-,sizeof nxt);
REP(i,,n) REP(j,,m)
{
int w=getint();
add_edge(hsh[i][j-],hsh[i][j],w),
add_edge(hsh[i][j],hsh[i][j-],w);
}
REP(i,,n) REP(j,,m)
{
int w=getint();
add_edge(hsh[i-][j],hsh[i][j],w),
add_edge(hsh[i][j],hsh[i-][j],w);
}
REP(i,,n) REP(j,,m)
{
int w=getint();
add_edge(hsh[i-][j-],hsh[i][j],w),
add_edge(hsh[i][j],hsh[i-][j-],w);
}
printf("%d\n",SAP(,cardP,cardP));
return ;
}

  然后对偶图最短路。。(被队列长度卡了好久。。用了循环队列才过。。)

 #pragma GCC optimize(2)
#include <algorithm>
#include <cstring>
#include <functional>
#define REP(i,low,high) for(register int i=(low);i<=(high);++i)
#define INF (0x3f3f3f3f)
#define function(type) __attribute__((optimize("-O2"))) inline type
#define procedure __attribute__((optimize("-O2"))) inline void
using namespace std; //ex_cmp {
template<typename T,class Compare>
inline bool getcmp(T&target,const T&pattern,Compare comp)
{
return comp(pattern,target)?target=pattern,:;
}
//} ex_cmp //quick_io {
#include <cctype>
#include <cstdio>
function(long long) getint()
{
char c=getchar(); for(;!isdigit(c)&&c!='+'&&c!='-';c=getchar());
short s=; for(;c=='+'||c=='-';c=getchar()) if(c=='-') s*=-;
long long r=; for(;isdigit(c);c=getchar()) r=(r<<)+(r<<)+c-'';
return s*r;
}
//} quick_io static const int N=,M=,SIZE=(N<<)+; struct edge
{
int to,cap; edge(const int&t=,const int&c=):to(t),cap(c) {}
}edg[(M<<)+]; static int cardE=; int hed[N+],nxt[(M<<)+]; procedure add_edge(const int&fr,const int&to,const int&cp)
{
edg[++cardE]=edge(to,cp),nxt[cardE]=hed[fr],hed[fr]=cardE;
} //SPFA {
bool inq[N+]={}; int dis[N+]={},q[SIZE]; function(int&) move(int&n) {return ++n==SIZE?n=:n;} function(int) SPFA(const int&S,const int&T)
{
memset(dis,0x3f,sizeof dis),inq[q[dis[S]=]=S]=;
for(register int head=-,tail=;head!=tail;)
{
int fr=q[move(head)];
for(register int i=hed[fr];i;i=nxt[i])
{
int to=edg[i].to;
if(
getcmp(dis[to],dis[fr]+edg[i].cap,less<int>())
&&!inq[to]
) inq[q[move(tail)]=to]=;
}
inq[fr]=;
}
return dis[T];
}
//} SPFA int main()
{
int n=getint(),m=getint(),nm=(n-)*(m-)<<;
if(n==||m==)
{
int ans=INF;
REP(i,,max(m,n)-) getcmp(ans,(int)getint(),less<int>());
return printf("%d\n",ans),;
}
REP(i,,m-)
{
int w=getint(); add_edge(i,nm+,w),add_edge(nm+,i,w);
}
REP(i,,n-) REP(j,,m-)
{
int w=getint(),fr=(i<<)*(m-)+j,to=fr-m+;
add_edge(fr,to,w),add_edge(to,fr,w);
}
REP(i,,m-)
{
int w=getint(),tmp=((n<<)-)*(m-)+i;
add_edge(,tmp,w),add_edge(tmp,,w);
}
REP(i,,n-)
{
int w=getint(),tmp=(i<<)*(m-)+m;
add_edge(,tmp,w),add_edge(tmp,,w);
REP(j,,m-)
{
int fr=(i<<)*(m-)+j-,to=fr+m;
add_edge(fr,to,w=getint()),add_edge(to,fr,w);
}
tmp=(m-)*(i<<|),w=getint(),
add_edge(tmp,nm+,w),add_edge(nm+,tmp,w);
}
REP(i,,n-) REP(j,,m-)
{
int w=getint(),fr=(i<<)*(m-)+j,to=fr+m-;
add_edge(fr,to,w),add_edge(to,fr,w);
}
printf("%d\n",SPFA(,nm+));
return ;
}

bzoj1001题解的更多相关文章

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

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

  2. 【题解】狼抓兔子—BZOJ1001。

    (胡扯时间)今天炒鸡无聊就打算BZOJ开始从第一道题开始顺着打,这样未来一段时间内也就有事干了.结果发现A+B切掉后就遭遇了一个"小小"的瓶颈(真不友好. 好了说题说题.看题第一眼 ...

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

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

  4. BZOJ1001 狼抓兔子 题解

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

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

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

  6. BZOJ1001 [BeiJing2006]狼抓兔子 最小割 对偶图 最短路

    原文链接http://www.cnblogs.com/zhouzhendong/p/8686871.html 题目传送门 - BZOJ1001 题意 长成上面那样的网格图求最小割. $n,m\leq ...

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

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

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

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

  9. BZOJ1001/LG4001 「ICPC Beijing2006」狼抓兔子 平面图最小割转对偶图最短路

    问题描述 BZOJ1001 LG4001 题解 平面图最小割=对偶图最短路 假设起点和终点间有和其他边都不相交的一条虚边. 如图,平面图的若干条边将一个平面划分为若干个图形,每个图形就是对偶图中的一个 ...

随机推荐

  1. eclipse Tomcat8.0端口占用报错和发布路径修改

    实际上我是eclipse莫名其妙调试时崩了,结果再启动也无法启动tomcat报端口占用错 修改server.xml里的端口号不是好方法,改完运行报   “ 对不起! 这里不是Web服务器” 后来研究发 ...

  2. Python文件路径操作

    print(os.environ.get('HOME')) # 打印`HOME`这个环境变量 /Users/<> file_path = os.environ.get('HOME') + ...

  3. 【leetcode】965. Univalued Binary Tree

    题目如下: A binary tree is univalued if every node in the tree has the same value. Return true if and on ...

  4. phpStudy的安装和配置

    一,下载工具 官网:http://www.phpstudy.net/,选择自己要安装的版本 二.多个站点和域名配置 1.打开phpStudy=>点击“其它选项菜单”=>点击“站点域名管理” ...

  5. PHP ftp_chdir() 函数

    定义和用法 ftp_chdir() 函数改变 FTP 服务器上的当前目录为指定目录. 如果成功,该函数返回 TRUE.如果失败,则返回 FALSE 和一个警告. 语法 ftp_chdir(ftp_co ...

  6. 在Visual C++中使用内联汇编

    一.内联汇编的优缺点 因为在Visual C++中使用内联汇编不需要额外的编译器和联接器,且可以处理Visual C++中不能处理的一些事情,而且可以使用在C/C++中的变量,所以非常方便.内联汇编主 ...

  7. hihoCoder [Offer收割]编程练习赛3 D子矩阵求和

    子矩阵求和 http://hihocoder.com/discuss/question/3005 声明一下: n是和x一起的,m是和y一起的 x是横着的,y是纵着的,x往右为正,y往下为正 (非常反常 ...

  8. jmter 5.1 中文

    一.jmeter5.0下载解压后,默认的界面是英文版的,许多人觉得不方便,想要汉化,jmeter是不需要安装汉化包的,通过修改配置文件即可:1.找到jmeter解压后的文件夹,例如我是安装在D:\De ...

  9. 19、Page Object 实例

    项目目录介绍: CalcuatorPage.java文件代码: package example; import io.appium.java_client.android.AndroidDriver; ...

  10. 【C++】清空一个C++栈的快速方法

    来源:https://stackoverflow.com/questions/40201711/how-can-i-clear-a-stack-in-c-efficiently/40201744 传统 ...