BZOJ1001: [BeiJing2006]狼抓兔子 (最小割转最短路)

浅析最大最小定理在信息学竞赛中的应用---周东

↑方法介绍

对于一个联通的平面图G(满足欧拉公式) 在s和t间新连一条边e;

然后建立一个原图的对偶图G*,G*中每一个点对应原图中每一个面,每一条边对应分割面的每一条边;

那么对偶图G*中,以原图s和t间边e新划分出的面作为起点(s*),最外的面作为终点(t*);

那么从s*到t*的每一条路都是原图G的一个割;

下图来自上方标出百度文库网址的ppt;

然后用堆(优先队列)优化的迪杰斯特拉,复杂度 O((m+n)logn) n为点数,m为边数...

嗯存一个堆优化迪杰斯特拉的代码...很久以前那个没有标签的一通好找..

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<queue>
 7 using namespace std;
 8 #define pa pair<int,int>
 9 int n,m,s,t;
10 struct node{
11     int y;
12     int next;
13     int v;
14 }e[6000100];
15 int head[2000100]={},tot=0,dis[2000100]={};
16 bool vis[2000100]={};
17 priority_queue< pa, vector< pa >, greater< pa > >q;
18 inline void init(int x,int y,int v){
19     e[++tot].y=y;
20     e[tot].next=head[x];
21     e[tot].v=v;
22     head[x]=tot;
23 }
24 inline int ge(int x,int y,int k){//x行,y列,在斜线的左(1)右(2);返回格子的编号
25     return 2*(x-1)*(m-1)+2*(y-1)+k;
26 }
27 /*
28 事实上如果按照从上到下从左到右来编号,在输入时的块编号是有规律的;
29 不一定要像上面一样这样找格子编号;
30 */
31 void doit(){
32     memset(dis,63,sizeof(dis));
33     int x,y;
34     dis[s]=0;
35     q.push(make_pair(0,s));
36     while(!q.empty()){
37         x=q.top().second;
38         q.pop();
39         if(vis[x]){
40             continue;
41         }
42         vis[x]=1;
43         for(int i=head[x];i;i=e[i].next){
44             y=e[i].y;
45             if(dis[y]>dis[x]+e[i].v){
46                 dis[y]=dis[x]+e[i].v;
47                 vis[y]=0;
48                 q.push(make_pair(dis[y],e[i].y));
49             }
50         }
51     }
52 }
53 int main(){
54     scanf("%d%d",&n,&m);
55     int v;
56     t=(m-1)*(n-1)*2+2;
57     s=t-1;
58     for(int i=1;i<=n;i++){
59         for(int j=1;j<m;j++){
60             scanf("%d",&v);
61             if(i==1){
62                 init(s,2*j,v);
63                 init(2*j,s,v);
64             }else if(i==n){
65                 init(ge(n-1,j,1),t,v);
66                 init(t,ge(n-1,j,1),v);
67             }else{
68                 init(ge(i-1,j,1),ge(i,j,2),v);
69                 init(ge(i,j,2),ge(i-1,j,1),v);
70             }
71         }
72     }
73     for(int i=1;i<n;i++){
74         for(int j=1;j<=m;j++){
75             scanf("%d",&v);
76             if(j==1){
77                 init(t,ge(i,1,1),v);
78                 init(ge(i,1,1),t,v);
79             }else if(j==m){
80                 init(ge(i,m-1,2),s,v);
81                 init(s,ge(i,m-1,2),v);
82             }else{
83                 init(ge(i,j-1,2),ge(i,j,1),v);
84                 init(ge(i,j,1),ge(i,j-1,2),v);
85             }
86         }
87     }
88     for(int i=1;i<n;i++){
89         for(int j=1;j<m;j++){
90             scanf("%d",&v);
91             init(ge(i,j,1),ge(i,j,2),v);
92             init(ge(i,j,2),ge(i,j,1),v);
93         }
94     }
95     doit();
96     printf("%d\n",dis[t]);
97     return 0;
98 }

时间: 2024-08-03 14:14:19

BZOJ1001: [BeiJing2006]狼抓兔子 (最小割转最短路)的相关文章

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

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1001 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: 左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 1:(x,y)<==>(x+1,y) 2:(x,y)<==>(x,y+1) 3:(x,y)

bzoj 1001 [BeiJing2006]狼抓兔子 最小割+最短路

题面 题目传送门 解法 将最大流转化成最小割,然后跑最短路即可 具体如何见图可以参考下图 尽量用dijkstra 代码 #include <bits/stdc++.h> #define PI pair <int, int> #define mp make_pair #define N 1010 using namespace std; template <typename node> void chkmax(node &x, node y) {x = max(x

bzoj1001 [BeiJing2006]狼抓兔子

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

BZOJ1001: [BeiJing2006]狼抓兔子【最短路】

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1001 1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 27684  Solved: 7127 Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的

[bzoj1001][BeiJing2006]狼抓兔子-题解[平面图最小割转最短路]/[Dinic求最小割]

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) 道路上的权值表示这条路上最多能够通过的兔子数,道路

BZOJ1001[BeiJing2006]狼抓兔子(无向图最小割)

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1001 这题的题意其实就是求一个最小割,但是由于是无向图,所以加边的时候,两边的流量都要是输入的权值,然后就是一个dinic求一下最小割. 但是这题貌似有很高超的技巧来搞,可以把平面图上的最小割转成对偶图上的最短路来做,这样可以起到很明显的优化效果.现在还不是很明白,如果以后明白了,会再来更新. dinic: #include <cstdio> #include <cstring&g

[BJOI2006][bzoj1001] 狼抓兔子 [最小割]

题面: 传送门 思路: 其实就是一道最小割的题目...... 我的写法加了两个优化,常数比较小,所以过掉了 一个是当前弧,一个是若当前点并不能流出去,那么标记dep为-1 听说正解是对偶图最短路?可以找时间学一学...... Code: #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define inf 1e9 #define id(i,j) (i-1)*

BZOJ 1001 Beijing 2006 狼抓兔子 最小割

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

[BZOJ1001] [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) 道路上的权值表示这条路上最多能够通过的兔子数,道路是