【BZOJ 1001】【Beijing 2006】狼抓兔子

看到这题,是个OIer应该都能想到最小割,然后条件反射写最大流,然后敲ISAP,Dinic,.......然后TLE掉了= =

 = =

本蒟蒻就是这样,然后去ym了各种题解,最后发现这是一个特殊的最大流模型,可以转化为最短路。现在讲一下详细建图方法。详见《两极相通—浅析最大最小定理在信息学竞赛中的应用》by 周冬

显然这个图是一个平面图,并且s,t在两个没有边界的平面上,这样的图称为s-t平面图,s-t上的最大流=最小割=对偶图上的最短路。

那么什么是对偶图呢,就是把每个平面当作点,平面与平面的公共边变成点与点之间的双向边,如何区分对偶图的s‘,t‘呢,把原图的s,t连起来,构成一个新的平面,新平面视作s‘,无限面视作t‘,注意对偶图中s‘,t‘之间的边要删去。形象一点,上个图(源自周冬论文):

很显然最小割变成了新图的最短路(证明见论文),原图的每一可行割,对应新图的每一可行路径,问题至此转化为对偶图上最短路。code:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
struct hp{
	int v,c;
}a[6000200];
int queue[4000200];
bool exist[2000200];
int point[2000200],next[6000200],dis[2000020];
int n,m,e=1;
void add(int u,int v,int c)
{
	e++; a[e].v=v; a[e].c=c; next[e]=point[u]; point[u]=e;
	e++; a[e].v=u; a[e].c=c; next[e]=point[v]; point[v]=e;
}
int spfa()
{
	int head,tail,u,i;
	memset(exist,false,sizeof(exist));
	memset(dis,127/3,sizeof(dis));
	head=0; tail=1; queue[tail]=0; dis[0]=0; exist[0]=true;
	while (head!=tail)
	  {
	    head=head%4000200+1;
		u=queue[head]; exist[u]=false;
		for (i=point[u];i;i=next[i])
		  {
		    if (dis[a[i].v]>dis[u]+a[i].c)
		      {
		        dis[a[i].v]=dis[u]+a[i].c;
		        if (!exist[a[i].v])
		          {
		            tail=tail%4000200+1;
				    exist[a[i].v]=true;
		            queue[tail]=a[i].v;
		          }
		      }
	      }
	  }
	return dis[2*(n-1)*(m-1)+1];
}
int main()
{
	int i,j,x,ans=2100000000;
	scanf("%d%d",&n,&m);
	for (i=1;i<=n;++i)
      for (j=1;j<=m-1;++j)
        {
          scanf("%d",&x);
          if (n==1)
		    ans=min(ans,x);
		  if (i==1)
		    add(j,2*(n-1)*(m-1)+1,x);
		  if (i>1&&i<n)
		    add((m-1)*2*(i-1)+j,(m-1)*(2*(i-1)-1)+j,x);
		  if (i==n)
		    add(0,(m-1)*(2*(n-1)-1)+j,x);
        }
    for (i=1;i<=n-1;++i)
      for (j=1;j<=m;++j)
        {
          scanf("%d",&x);
          if (m==1)
            ans=min(ans,x);
          if (j==1)
            add(0,(m-1)*(2*i-1)+1,x);
          if (j>1&&j<m)
            add((m-1)*(2*(i-1))+j-1,(m-1)*(2*i-1)+j,x);
          if (j==m)
            add((m-1)*(2*i-1),2*(n-1)*(m-1)+1,x);
        }
    for (i=1;i<=n-1;++i)
      for (j=1;j<=m-1;++j)
        {
          scanf("%d",&x);
		  add((m-1)*(2*i-1)+j,2*(m-1)*(i-1)+j,x);
        }
    if (n==1&&m==1)
      printf("0\n");
    else
      {
        if (n==1||m==1) printf("%d\n",ans);
        else printf("%d\n",spfa());
      }
}
时间: 2024-11-06 04:51:38

【BZOJ 1001】【Beijing 2006】狼抓兔子的相关文章

BZOJ 1001 Beijing 2006 狼抓兔子 最小割

题目大意:有一张无向图,描述的是兔子窝的位置和之间的边.现在狼来抓兔子了,兔子慌忙的从(1,1)逃走到(m,n).每条边上都有能通过最多的兔子数量.狼不想让兔子逃走,每在一条边驻守一只狼就可以避免一个兔子通过.问最少多少狼可以让所有兔子都不能逃走. 思路:建图,按题目中的意思是去掉最小的边使得源到汇不连通,显然的最小割. CODE: #include <queue> #include <cstdio> #include <cstring> #include <io

BZOJ 1001 [BJOI 2006] 狼抓兔子

BZOJ题面 瑾以此题纪念博主迈出冲刺省选的第一步 打眼一看,这不是裸的最小割吗? 最小割 == 最大流: 然后 5 分钟码完 ISAP : 交上去一看......TLE......懵逼...... 然后进行了一波没有卵用的优化常数...... (去他妈的 1e6 个点,3e6 条边!!!) 问了问度娘,才知道这题的图是 '平面图' : 平面图的最小割和最大流可以通过将其转换成对偶图跑最短路求解:(涨姿势) 那么什么是对偶图呢? 通俗的讲,对偶图就是把原图的点换成面(边围成的区域),面换成点,而

【BZOJ 1001】[BeiJing2006]狼抓兔子

Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: 左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 1:(x,y)<==>(x+1,y) 2:(x,y)<==>(x,y+1) 3:(x,y)<==>(x+1,y+1) 道路上的权值表示这条路上最多能够通过的兔子数,道路是

BZOJ 1001:[BeiJing2006]狼抓兔子(最小割)

http://www.lydsy.com/JudgeOnline/problem.php?id=1001 题意:中文. 思路:很明显是最小割,转化为最大流做.一开始看那么多点,但还是试了一下,居然过了.迷. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <queue> 6 using namespac

解题:BJOI 2006 狼抓兔子

题面 可以看出来是最小割,然后你就去求最大流了 这么大的范围就是让你用网络流卡的?咋想的啊=.=??? 建议还是老老实实用 平面图最小割等于其对偶图最短路 这个东西来做吧,虽然这个东西跑的也挺慢的,最后一个点跑了$2s$ 对偶图就是被边分割出来的每个区域当成一个点,然后两个区域有公共边就连边,起点和终点的问题就在源汇点中间连一条边然后就能分出来了 1 #include<queue> 2 #include<cstdio> 3 #include<cctype> 4 #inc

ICPC-Beijing 2006 狼抓兔子

题目描述 题解: 裸的最小割. 但是最大流跑不过去怎么办? 转变一下,既然最大流是一条左下<->右上的通路,我们可以把图划分为若干区域, 最后找左下到右上的最短路就行了. 代码: #include<queue> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int N = 1100; t

bzoj1001 [ICPC-Beijing 2006]狼抓兔子

我满心以为本题正解为最短路,结果到处都是最大流-- 几乎所有的都写了什么"对偶图"跑最短路~~,但我真的不知道什么叫做对偶图~~-------------------------------------------------------------------------------------------------介绍一下本题的最短路算法叭.并不算难.主要是感性理解. 首先很容易观察出这是一个最小割,那么就是求最大流了. 但是这题的点数高达10e6,按常理来说最大流应该稳稳地TL

Luogu P4001 [ICPC-Beijing 2006]狼抓兔子

Link 平面图的最小割等于其对偶图的最短路. 虽然我不会证但感觉确实挺好理解的. #include<queue> #include<cstdio> #include<cctype> #include<vector> #include<cstring> #include<utility> #include<functional> #define pi pair<int,int> #define fi first

【BZOJ】1001: [BeiJing2006]狼抓兔子

1001: [BeiJing2006]狼抓兔子 Description 左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下 三种类型的道路 1:(x,y)<==>(x+1,y) 2:(x,y)<==>(x,y+1) 3:(x,y)<==>(x+1,y+1) 道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的. 左上角和右下角为兔子的两个窝,开始时所有的兔子都聚集在左上角(1,1)的窝里,现在它们要跑到右下角(N,M)的窝中去,狼王开始伏击

BZOJ 1001: [BeiJing2006]狼抓兔子【最大流/SPFA+最小割,多解】

1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 23822  Solved: 6012[Submit][Status][Discuss] Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: 左上角点为(1,1),右下角点为(N,M)(上图中N=4,M