• BZOJ 1001 题解


    1001: [BeiJing2006]狼抓兔子

    Time Limit: 15 Sec  Memory Limit: 162 MB
    Submit: 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

    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 ( "
    " ) ;
    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
    " , Dis[ ( N - 1 ) * ( M - 1 ) * 2 + 2 ] ) ;
    96         //DEBUG_( N , M ) ;
    97           
    98         return 0 ;
    99 } 
    View Code

    2016-10-12 23:35:00

     

    (完)

     

  • 相关阅读:
    这个帖子主要总结数据库备份方面的问题
    Visual C#.Net 网络程序开发Socket篇
    数据库设计说明书参考模板
    用Visual C#开发WinForm的应用程序
    在ASP.NET页中读取文本文件
    如何通过 SQL Server 链接服务器和分布式查询使用 Excel
    ER概念模型
    SQL Server 存储过程的分页方案比拼
    读出某一个目录的文件和文件夹
    Linux中的定时任务简单操作实例
  • 原文地址:https://www.cnblogs.com/shadowland/p/5954862.html
Copyright © 2020-2023  润新知