bzoj1001题解
【解题思路】
显然,这题的答案是这个网格图的最小割。根据最大流-最小割定理,我们可以用网络流算法来求其最小割,时间复杂度最小为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题解的更多相关文章
- 【bzoj1001】【最短路】【对偶图】【最大流转最小割】狼抓兔子题解
[BZOJ1001]狼抓兔子 1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 18872 Solved ...
- 【题解】狼抓兔子—BZOJ1001。
(胡扯时间)今天炒鸡无聊就打算BZOJ开始从第一道题开始顺着打,这样未来一段时间内也就有事干了.结果发现A+B切掉后就遭遇了一个"小小"的瓶颈(真不友好. 好了说题说题.看题第一眼 ...
- BZOJ1001 洛谷4001 [BJOI2006]狼抓兔子 题解
题目 这个题目有多种解法,这个题也是一个比较经典的题了,正是因为他的多样的做法,这个题主要难在建图和优化,因为这是一个网格图,所以spfa肯定过不去,所以用最短路解法的话,只能用dij,而网络流也是要 ...
- BZOJ1001 狼抓兔子 题解
裸的最小割,转化成最大流即可. #include <bits/stdc++.h> int n,m; int S,T; int mincost; int head[6001000],tot= ...
- 【BZOJ1001】狼抓兔子(网络流)
[BZOJ1001]狼抓兔子(网络流) 题面 Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨, ...
- BZOJ1001 [BeiJing2006]狼抓兔子 最小割 对偶图 最短路
原文链接http://www.cnblogs.com/zhouzhendong/p/8686871.html 题目传送门 - BZOJ1001 题意 长成上面那样的网格图求最小割. $n,m\leq ...
- 【BZOJ1001】[BeiJing2006]狼抓兔子 对偶图最短路
[BZOJ1001][BeiJing2006]狼抓兔子 Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子 ...
- 【BZOJ1001】狼抓兔子(平面图转对偶图,最短路)
[BZOJ1001]狼抓兔子(平面图转对偶图,最短路) 题面 BZOJ 洛谷 题解 这题用最小割可以直接做 今天再学习了一下平面图转对偶图的做法 大致的思路如下: 1.将源点到汇点中再补一条不与任何线 ...
- BZOJ1001/LG4001 「ICPC Beijing2006」狼抓兔子 平面图最小割转对偶图最短路
问题描述 BZOJ1001 LG4001 题解 平面图最小割=对偶图最短路 假设起点和终点间有和其他边都不相交的一条虚边. 如图,平面图的若干条边将一个平面划分为若干个图形,每个图形就是对偶图中的一个 ...
随机推荐
- 【Luogu】【关卡2-12】递推与递归二分(2017年10月)
任务说明:递推,层层递进,由基础推向顶层.二分不仅可以用来查找数据,还可以确定最合适的值. P1192 台阶问题 有N级的台阶,你一开始在底部,每次可以向上迈最多K级台阶(最少1级),问到达第N级台阶 ...
- taro-安装及使用-npm
taro-安装及使用 https://nervjs.github.io/taro/docs/GETTING-STARTED.html 安装 Taro 项目基于 node,请确保已具备较新的 node ...
- springcloud feign增加熔断器Hystrix
1.依赖 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>s ...
- springBoot和MyBatis整合中出现SpringBoot无法启动时处理方式
在springBoot和Myatis 整合中出现springBoot无法启动 并且报以下错误 Description: Field userMapper in cn.lijun.control ...
- 帝国CMS数据库数据表详细说明
表名 解释 phome_ecms_infoclass_news 新闻采集规则记录表 phome_ecms_inf ...
- 使用PHP和MySQL添加数据库时的小错误及注意事项总结
刚刚开始使用PHP和MySQL搭配着,从前端往数据库传数据,错误犯了不少,总结一下,提醒自己 1.写MySQL语句时,标点符号使用错 正确的应该是 $sql = "INSERT INTO ` ...
- java 原生 HttpClient
package org.rx.socks.http; import com.google.common.base.Strings; import lombok.SneakyThrows; import ...
- 2019杭电多校第一场hdu6579 Operation(线性基)
Operation 题目传送门 解题思路 把右边的数尽量往高位放,构造线性基的时候同时记录其在原序列中的位置,在可以插入的时候如果那个位置上存在的数字的位置比新放入的要小,就把旧的往后挤.用这种发现构 ...
- 拾遗:Docker 基本应用
https://wiki.gentoo.org/wiki/Docker 检查内核内核选项 exec /usr/share/docker/contrib/check-config.sh 使用 btrfs ...
- Kali Linux 2018 更新源配置
查看添加更新源 编辑sources.list,将kali更新源加入其中 sudo vim /etc/apt/sources.list 国内更新源 #阿里云 deb http://mirrors.ali ...