• 1001. [BJOI2006]狼抓兔子【最小割】


    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
     
    比较裸的一个题,记得建立双向边
    建立双向变有个小技巧,就是正反边流量都为正数
     
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<queue>
     5 #define N (2000000+10)
     6 using namespace std;
     7 struct node
     8 {
     9     int to,next,Flow;
    10 }edge[N<<2];
    11 int n,m,x,s,e;
    12 int head[N],num_edge;
    13 int Depth[N]; 
    14 queue<int>q;
    15 
    16 void add(int u,int v,int l)
    17 {
    18     edge[++num_edge].to=v;
    19     edge[num_edge].Flow=l;
    20     edge[num_edge].next=head[u];
    21     head[u]=num_edge;
    22 }
    23 
    24 bool Bfs(int s,int e)
    25 {
    26     memset(Depth,0,sizeof(Depth));
    27     Depth[s]=1;
    28     q.push(s);
    29     while (!q.empty())
    30     {
    31         int x=q.front();
    32         q.pop();
    33         for (int i=head[x];i!=0;i=edge[i].next)
    34             if (!Depth[edge[i].to] && edge[i].Flow>0)
    35             {
    36                 Depth[edge[i].to]=Depth[x]+1;
    37                 q.push(edge[i].to);
    38             }
    39     }
    40     return Depth[e]!=0;
    41 }
    42 
    43 int Dfs(int x,int low)
    44 {
    45     int Min,f=0;
    46     if (x==e || low==0)    return low;
    47     for (int i=head[x];i!=0;i=edge[i].next)
    48         if (edge[i].Flow>0 && Depth[edge[i].to]==Depth[x]+1 && (Min=Dfs(edge[i].to,min(edge[i].Flow,low))))
    49         {
    50             edge[i].Flow-=Min;
    51             edge[((i-1)^1)+1].Flow+=Min;
    52             f+=Min;
    53             low-=Min;
    54             if (low==0) return f;
    55         }
    56     if (f==0) Depth[x]=0;
    57     return f;
    58 }
    59 
    60 int Dinic(int s,int e)
    61 {
    62     int Ans=0;
    63     while (Bfs(s,e))
    64         Ans+=Dfs(s,0x7fffffff);
    65     return Ans;
    66 }
    67 
    68 int main()
    69 {
    70     scanf("%d%d",&n,&m);//n行m列 
    71     s=1,e=n*m;
    72     for (int i=1;i<=n;++i)
    73         for (int j=1;j<=m-1;++j)
    74         {
    75         
    76             scanf("%d",&x);
    77             add((i-1)*m+j,(i-1)*m+j+1,x);
    78             add((i-1)*m+j+1,(i-1)*m+j,x);
    79         }
    80     for (int i=1;i<=n-1;++i)
    81         for (int j=1;j<=m;++j)
    82         {
    83             scanf("%d",&x);
    84             add((i-1)*m+j,i*m+j,x);
    85             add(i*m+j,(i-1)*m+j,x);
    86         }
    87     for (int i=1;i<=n-1;++i)
    88         for (int j=1;j<=m-1;++j)
    89         {
    90             scanf("%d",&x);
    91             add((i-1)*m+j,i*m+j+1,x);
    92             add(i*m+j+1,(i-1)*m+j,x);
    93         }
    94     printf("%d",Dinic(s,e));
    95 }
  • 相关阅读:
    什么是“开放构造类型”,“封闭构造类型”
    代码整洁整洁之道读书笔记 2
    学习 WCF By Visual Studio 2010 (1)起步“全双工”
    代码整洁整洁之道读书笔记 1
    学习 WCF By Visual Studio 2010 (2) 宿主
    持久层通用组件设计与范例,写给某孩子(基于JDBC)
    [zz]JS后退一页, JS返回上一页代码, JS返回下一页,JS返回第几页,JS页面跳转, JS引用JS
    web下vs2008+crystal report 不预览直接打印
    用SQL语句删除重复记录
    Gridview 添加行.
  • 原文地址:https://www.cnblogs.com/refun/p/8680734.html
Copyright © 2020-2023  润新知