• BZOJ_1001_狼抓兔子_(平面图求最小割+对偶图求最短路)


    描述


    http://www.lydsy.com/JudgeOnline/problem.php?id=1001

    1001: [BeiJing2006]狼抓兔子

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

     2015.4.16新加数据一组,可能会卡掉从前可以过的程序。

    Source

    分析


    平面图求最小割,转化成对偶图求最短路,经典.

    注意:

    1.优先队列是个大根堆.

    2.Dijkstra可以带一个vis数组,也可以不带,因为一个点出来以后,它更新的的点和原本就在队列里的点都比它大,所以它不可能被更新得更小,之后这个点再出队时情况不比第一次更优,所以出队也不会有操作.

    3.双向边,数组要开够(貌似不是第一次犯这个错误).

    4.网上有人说m==1||n==1的情况可以不特判,在get函数中已经可以处理妥当,大丈夫.

     1 #include <cstdio>
     2 #include <queue>
     3 #include <algorithm>
     4 using namespace std;
     5  
     6 const int maxn=1000+10,oo=1<<27;
     7 int n,m,cnt;
     8 int d[maxn*maxn*2],head[maxn*maxn*4];
     9 bool vis[maxn*maxn*2];
    10 struct edge{
    11     int to,w,next;
    12     edge(){}
    13     edge(int a,int b,int c):to(a),w(b),next(c){}
    14     bool operator<(const edge &a) const { return a.w<w; }
    15 }g[maxn*maxn*6];
    16 void insert(int from,int to,int w){
    17     g[++cnt]=edge(to,w,head[from]); head[from]=cnt; 
    18     g[++cnt]=edge(from,w,head[to]); head[to]=cnt;
    19 }
    20  
    21 int get(int x,int y,int z){
    22     if(x<1||y>=m) return ((n-1)*(m-1)<<1)+1;
    23     if(x>=n||y<1) return 0;
    24     return (((x-1)*(m-1)+y-1)<<1)+z+1;
    25 }
    26 int Dijkstra(int s,int t){
    27     for(int i=0;i<=((n-1)*(m-1)<<1)+1;i++) d[i]=oo;
    28     d[s]=0;
    29     priority_queue <edge> q;
    30     q.push(edge(s,0,0));
    31     while(!q.empty()){
    32         edge e=q.top(); q.pop();
    33         int x=e.to;
    34         if(vis[x]) continue;
    35         vis[x]=true;
    36         for(int i=head[x];i;i=g[i].next){
    37             int y=g[i].to;
    38             if(d[y]>d[x]+g[i].w){
    39                 d[y]=d[x]+g[i].w;
    40                 q.push(edge(y,d[y],0));
    41             }
    42         }
    43     }
    44     return d[t];
    45 }
    46  
    47 void init(){
    48     for(int i=1;i<=n;i++){
    49         for(int j=1;j<m;j++){
    50             int a; scanf("%d",&a);
    51             insert(get(i,j,1),get(i-1,j,0),a);
    52         }
    53     }
    54     for(int i=1;i<n;i++){
    55         for(int j=1;j<=m;j++){
    56             int a; scanf("%d",&a);
    57             insert(get(i,j-1,1),get(i,j,0),a);
    58         }
    59     }
    60     for(int i=1;i<n;i++){
    61         for(int j=1;j<m;j++){
    62             int a; scanf("%d",&a);
    63             insert(get(i,j,0),get(i,j,1),a);
    64         }
    65     }
    66 }
    67  
    68 int main(){
    69     scanf("%d%d",&n,&m);
    70     init();
    71     printf("%d
    ",Dijkstra(0,((n-1)*(m-1)<<1)+1));
    72     return 0;
    73 }
    View Code

     

  • 相关阅读:
    Iso-seq 必备基础
    html 段落
    html 标题
    html 简介
    motiMaker 软件安装测试
    ggplot2 提取stat计算出来的数据
    R包 randomForest 进行随机森林分析
    AJAX应用【股票案例、验证码校验】
    Servlet第二篇【Servlet调用图、Servlet细节、ServletConfig、ServletContext】
    Servlet第一篇【介绍Servlet、HTTP协议、WEB目录结构、编写入门Servlet程序、Servlet生命周期】
  • 原文地址:https://www.cnblogs.com/Sunnie69/p/5491265.html
Copyright © 2020-2023  润新知