zoukankan      html  css  js  c++  java
  • BZOJ-1001&洛谷P4001【BeiJing2006】狼抓兔子(网络流-最小割)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1001

    Time Limit: 15 Sec  Memory Limit: 162 MB

    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新加数据一组,可能会卡掉从前可以过的程序。


    。。。很久没写过网络流的题目了,但还是一眼就看出来这是个最小割的题目了。。。只是没办法像以前一样手敲了,只能抄一遍板子。
    挺裸的一道网络流,建一下边,跑一遍Dinic算法就完事儿了,这里贡献一下我的板子:
    看了看数据。。。本来以为要么T了,要么MLE了。。。结果A了,不可思议!!!注意一下双向边,建两次边就完事了。
    以下是AC代码:(跑了2.5s多,空间差一点MLE。。150多MB)
    #include <bits/stdc++.h>
    using namespace std;
    
    const int mac=1e6+10;
    const int inf=5e8+10;
    
    struct Edge
    {
        int to,next,w;
    }eg[mac*12];
    int head[mac],num=0,dis[mac],cur[mac];
    int S,T;
    
    inline void add(int u,int v,int w)
    {
        eg[num]=Edge{v,head[u],w};
        head[u]=num++;
        eg[num]=Edge{u,head[v],0};
        head[v]=num++;
    }
    
    inline int bfs()
    {
        queue<int>q;
        memset(dis,0,sizeof dis);
        dis[S]=1;
        q.push(S);
        while (!q.empty()){
            int u=q.front();
            q.pop();
            for (int i=head[u]; i!=-1; i=eg[i].next){
                int v=eg[i].to;
                if (eg[i].w>0 && dis[v]==0){
                    dis[v]=dis[u]+1;
                    if (v==T) return 1;
                    q.push(v);
                }
            }
        }
        return 0;
    }
    
    inline int dfs(int u,int flow)
    {
        if (u==T || !flow) return flow;
        int sum=0,x=0;
        for (int i=cur[u]; i!=-1; i=eg[i].next){
            int v=eg[i].to;
            if (eg[i].w>0 && dis[v]==dis[u]+1){
                x=dfs(v,min(flow-sum,eg[i].w));
                eg[i].w-=x;
                eg[i^1].w+=x;
                if (eg[i].w) cur[u]=i;
                sum+=x;
                if (sum==flow) return flow;
            }
        }
        if (sum==0) dis[u]=0;
        return sum;
    }
    
    inline int dinic()
    {
        int sum=0;
        while (bfs()){
            for (int i=S; i<=T; i++)
                cur[i]=head[i];
            sum+=dfs(S,inf);
        }
        return sum;
    }
    
    inline void in(int &x)
    {
        int f=0;
        char ch=getchar();
        while (ch<'0' || ch>'9') ch=getchar();
        while (ch>='0' && ch<='9') f=(f<<1)+(f<<3)+ch-'0',ch=getchar();
        x=f;
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        memset(head,-1,sizeof head);
        int n,m;
        in(n);in(m);
        S=1,T=n*m;
        for (int i=1; i<=n; i++){
            for (int j=1; j<m; j++){
                int w;in(w);
                add((i-1)*m+j,(i-1)*m+j+1,w);
                add((i-1)*m+j+1,(i-1)*m+j,w);
            }
        }
        for (int i=1; i<n; i++){
            for (int j=1; j<=m; j++){
                int w;in(w);
                add((i-1)*m+j,i*m+j,w);
                add(i*m+j,(i-1)*m+j,w);
            }
        }
        for (int i=1; i<n; i++){
            for (int j=1; j<m; j++){
                int w;in(w);
                add((i-1)*m+j,i*m+j+1,w);
                add(i*m+j+1,(i-1)*m+j,w);
            }
        }
        int ans=dinic();
        printf("%d
    ",ans);
        return 0;
    }

    然后看看网上也有利用对偶图跑最短路的,降低了时间与空间,它只用了100MB左右,跑了1S(自己加了快读)。。。这里给出一个跑得比我快的最短路代码:

    https://www.cnblogs.com/reddest/p/5954756.html

     
    路漫漫兮
  • 相关阅读:
    2014-12-28 iframe,style,body style
    2014-12-25 网页基础,html。
    2014-12-19 特殊集合:stack、queue、Hashtable
    2014-12-18 集合
    2014-12-16 多维数组
    2014-12-15 数组
    2014-12-14 跳转语句,while循环,各种类的用法
    combobox DataGridView
    面向对象(重载、封装、继承、抽象)
    winform
  • 原文地址:https://www.cnblogs.com/lonely-wind-/p/12020102.html
Copyright © 2011-2022 走看看