首页 > 代码库 > BZOJ 1001 题解
BZOJ 1001 题解
1001: [BeiJing2006]狼抓兔子
Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 18876 Solved: 4649
[Submit][Status][Discuss]
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)的窝中去,狼王开始伏击这些兔子.当然为了保险起见,如果一条道路上最多通过的兔子数为K,狼王需要安排同样数量的K只狼,才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的狼的数量要最小。因为狼还要去找喜羊羊麻烦.
Input
第一行为N,M.表示网格的大小,N,M均小于等于1000.
接下来分三部分
第一部分共N行,每行M-1个数,表示横向道路的权值.
第二部分共N-1行,每行M个数,表示纵向道路的权值.
第三部分共N-1行,每行M-1个数,表示斜向道路的权值.
输入文件保证不超过10M
Output
输出一个整数,表示参与伏击的狼的最小数量.
Sample Input
3 4
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6
Sample Output
14
HINT
Source
——————————————————分割线——————————————————
这道题是一道很玄学的题目,我们不能直接求它的最小割,要通过它的对偶图的最短路。那么怎么完成呢?
这时,只需求点1到点14的最短路就行啦。
[ATTENTION]:这道题点数总共有( N - 1 ) * ( M - 1) * 2 + 2 个,本蒟蒻被坑了好久。注意数组大小!!!
推荐一个课件:浅析最大最小定理在信息学竞赛中的应用
1 /************************************************************** 2 Problem: 1001 3 User: shadowland 4 Language: C++ 5 Result: Accepted 6 Time:2752 ms 7 Memory:165356 kb 8 ****************************************************************/ 9 10 #include "bits/stdc++.h"11 12 using namespace std ;13 struct Edge { int to , next , val ; } ;14 const int maxN = 8000100 ;15 16 Edge e[ maxN ] ;17 int head[ maxN ] , Dis[ maxN ] ;18 bool vis[ maxN ] ;19 20 int N , M , cnt ;21 22 inline int INPUT ( ) {23 int x = 0 , f = 1 ; char ch = getchar ( ) ;24 while ( ch < ‘0‘ || ch > ‘9‘ ) { if ( ch == ‘-‘)f = -1 ; ch = getchar ( ) ;}25 while ( ch >= ‘0‘ && ch <= ‘9‘ ) { x = ( x << 1 ) + ( x << 3 ) + ch - ‘0‘ ; ch = getchar ( ) ;}26 return x * f ; 27 } 28 29 inline int Get ( const int x , const int y , const int z ) {30 if ( x < 1 || y >=M ) return ( N - 1 ) * ( M - 1 ) * 2 + 2 ;31 if ( x >= N || y < 1 ) return 1 ;32 return ( ( x - 1 ) * ( M - 1 ) + y ) *2 + z ;33 } 34 35 inline void Add_Edge ( const int x , const int y , const int _val ) {36 e[ ++cnt ].to = y ;37 e[ cnt ].val = _val ;38 e[ cnt ].next = head[ x ] ;39 head[ x ] = cnt ;40 }41 42 void SPFA ( const int S ) {43 memset ( vis , false , sizeof ( vis ) ) ;44 memset ( Dis , 0x3f , sizeof ( Dis ) ) ;45 queue < int > Q ; 46 Dis[ S ] = 0 ;47 vis[ S ] = true ;48 Q.push ( S ) ;49 while ( !Q.empty ( ) ) {50 int t = Q.front( ) ; Q.pop ( ) ; vis[ t ] = false ;51 for ( int i=head[ t ] ; i ; i = e[ i ].next ) {52 int temp = e[ i ].to ;53 if ( Dis[ temp ] > Dis[ t ] + e[ i ].val ) {54 Dis[ temp ] = Dis[ t ] + e[ i ].val ;55 if ( !vis[ temp ] ) {56 Q.push ( temp ) ;57 vis[ temp ] = true ;58 }59 }60 }61 }62 }63 64 void DEBUG_ ( int N , int M ) {65 printf ( "\n" ) ;66 for ( int i=1 ; i<=(( N - 1 ) * ( M - 1 ) * 2 + 2) ; ++i ) {67 printf ( "%d " , Dis[ i ] ) ;68 }69 }70 int main ( ) {71 int _val ; 72 scanf ( "%d %d" , &N , &M ) ;73 for ( int i=1 ; i<=N ; ++i ) {74 for ( int j=1 ; j<M ; ++j ) {75 _val = INPUT ( ) ;76 Add_Edge ( Get ( i , j , 1 ) , Get ( i - 1 , j , 0 ) , _val ) ;77 Add_Edge ( Get ( i - 1 , j , 0 ) , Get ( i , j , 1 ) , _val ) ;78 }79 }80 for ( int i=1 ; i<N ; ++i ) {81 for ( int j=1 ; j<=M ; ++j ) {82 _val = INPUT ( ) ;83 Add_Edge ( Get ( i , j - 1 , 1 ) , Get ( i , j , 0 ) , _val ) ;84 Add_Edge ( Get ( i , j , 0 ) , Get ( i , j - 1 , 1 ) , _val ) ;85 }86 }87 for ( int i=1 ; i<N ; ++i ) {88 for ( int j=1 ; j<M ; ++j ) {89 _val = INPUT ( ) ;90 Add_Edge ( Get ( i , j , 0 ) , Get ( i , j , 1 ) , _val ) ;91 Add_Edge ( Get ( i , j , 1 ) , Get ( i , j , 0 ) , _val ) ;92 }93 }94 SPFA ( 1 ) ;95 printf ( "%d\n" , Dis[ ( N - 1 ) * ( M - 1 ) * 2 + 2 ] ) ;96 //DEBUG_( N , M ) ;97 98 return 0 ;99 }
2016-10-12 23:35:00
(完)
BZOJ 1001 题解
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。