• 【bzoj1001】[BeiJing2006]狼抓兔子


    *题目描述:
    现在小朋友们最喜欢的”喜羊羊与灰太狼”,话说灰太狼抓羊不到,但抓兔子还是比较在行的,
    而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:

    bzoj1001

    左上角点为(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只狼,
    才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的
    狼的数量要最小。因为狼还要去找喜羊羊麻烦.
    *输入:
    第一行为N,M.表示网格的大小,N,M均小于等于1000.
    接下来分三部分
    第一部分共N行,每行M-1个数,表示横向道路的权值.
    第二部分共N-1行,每行M个数,表示纵向道路的权值.
    第三部分共N-1行,每行M-1个数,表示斜向道路的权值.
    输入文件保证不超过10M
    *输出:
    输出一个整数,表示参与伏击的狼的最小数量.
    *样例输入:
    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
    *样例输出:
    14
    *题解:
    SPFA跑不过Dinic系列。。。这题有两种做法,第一种直接依题意建图用Dinic跑最大流(题意就是要求一个最小割,然后用最大流来解决)。第二种就是把平面图的最小割对偶成最短路。把每一个三角形的区域看成是一个点,每一条原图的边看成是分割两个区域的边,然后题目就转化为了从左下到右上的最短距离,用最短路来解决。
    *代码:
    2016.02.23 *1 Dinic

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    
    #ifdef WIN32
        #define LL "%I64d"
    #else
        #define LL "%lld"
    #endif
    
    #ifdef CT
        #define debug(...) printf(__VA_ARGS__)
    #else
        #define debug(...)
    #endif
    
    #define R register
    #define getc() (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?EOF:*S++)
    #define gmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
    #define gmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
    #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
    #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
    char B[1<<15],*S=B,*T=B;
    inline int FastIn()
    {
        R char ch;R int cnt=0;R bool minus=0;
        while (ch=getc(),(ch < '0' || ch > '9') && ch != '-') ;
        ch == '-' ?minus=1:cnt=ch-'0';
        while (ch=getc(),ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
        return minus?-cnt:cnt;
    }
    #define maxn 1000010
    #define maxm 6000010
    #define INF 233333333
    int w[maxm],last[maxn],to[maxm],next[maxm],ecnt,ans,dep[maxn],s,t;
    int q[maxn];
    bool vis[maxn];
    #define add(_a,_b,_v) (to[++ecnt]=(_b),next[ecnt]=last[_a],last[_a]=ecnt,w[ecnt]=(_v))
    inline bool bfs(){
        memset(dep,-1,sizeof(dep));dep[t]=0;
        R int head=0,tail=1;q[1]=t;
        while (head<tail){
            head++;R int now=q[head];
            for (R int i=last[now];i;i=next[i]){
                R int pre=to[i];
                if (w[i^1]&&dep[pre]==-1){dep[pre]=dep[now]+1;q[++tail]=pre;}
            }
        }
        return dep[s]!=-1;
    }
    int dfs(R int x,R int f){
        if (x==t) return f;
        R int v,used=0;
        for (R int i=last[x];i;i=next[i]){
            R int pre=to[i];
            if (w[i]&&(dep[x]==dep[pre]+1)){
                R int v=dfs(pre,gmin(f-used,w[i]));
                w[i]-=v;
                w[i^1]+=v;
                used+=v;
                if (used==f) return used;
            }
        }
        if (!used) dep[x]=-1;
        return used;
    }
    inline void dinic(){
        while (bfs()) {ans+=dfs(s,INF);}
    }
    int main()
    {
        R int n=FastIn(),m=FastIn();s=1;t=n*m;ecnt=1;
        for (R int i=0;i<n;i++)
            for (R int j=1;j<m;j++){
                R int a=i*m+j,b=a+1,v=FastIn();
                add(a,b,v);add(b,a,v);
            }
        for (R int i=0;i<n-1;i++)
            for (R int j=1;j<=m;j++){
                R int a=i*m+j,b=a+m,v=FastIn();
                add(a,b,v);add(b,a,v);
            }
        for (R int i=0;i<n-1;i++)
            for (R int j=1;j<m;j++){
                R int a=i*m+j,b=a+m+1,v=FastIn();
                add(a,b,v);add(b,a,v);
            }
        dinic();
        printf("%d
    ",ans );
        return 0;
    }

    2016.05.17 *1 spfa

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    
    #ifdef WIN32
        #define LL "%I64d"
    #else
        #define LL "%lld"
    #endif
    
    #ifdef CT
        #define debug(...) printf(__VA_ARGS__)
        #define setfile() 
    #else
        #define debug(...)
        #define filename ""
        #define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout);
    #endif
    
    #define R register
    #define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++)
    #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
    #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
    #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
    #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
    char B[1 << 15], *S = B, *T = B;
    inline int FastIn()
    {
        R char ch; R int cnt = 0; R bool minus = 0;
        while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ;
        ch == '-' ? minus = 1 : cnt = ch - '0';
        while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
        return minus ? -cnt : cnt;
    }
    #define maxx 1010
    #define maxn 2000010
    #define maxm 10000010
    int id[maxx][maxx][2];
    struct Edge
    {
        Edge *next;
        int to, w;
    }*last[maxn], e[maxm], *ecnt = e;
    inline void link(R int a, R int b, R int w)
    {
        *++ecnt = (Edge) {last[a], b, w}; last[a] = ecnt;
        *++ecnt = (Edge) {last[b], a, w}; last[b] = ecnt;
    }
    int d[maxn];
    bool vis[maxn];
    std::queue <int> q;
    #define inf 0x7fffffff
    int main()
    {
    //  setfile();
        R int n = FastIn(), m = FastIn(), cnt = 0;
        if (!n || !m) return !printf("0
    ");
        if (n == 1 || m == 1)
        {
            R int minn = inf;
            if (m == 1) m = n, n = 1;
            for (R int i = 1; i < m; ++i)
            {
                R int val = FastIn();
                cmin(minn, val);
            }
            return !printf("%d
    ", minn == inf ? 0 : minn );
        }
        for (R int i = 1; i < n; ++i)
            for (R int k = 0; k <= 1; ++k)
                for (R int j = 1; j < m; ++j)
                    id[i][j][k] = ++cnt;
        R int s = 0, t = ++cnt;
        for (R int i = 1; i <= n; ++i)
        {
            if (i == 1)
                for (R int j = 1; j < m; ++j)
                    link(id[i][j][0], t, FastIn());
            else if (i == n)
                for (R int j = 1; j < m; ++j)
                    link(s, id[i - 1][j][1], FastIn());
            else
                for (R int j = 1; j < m; ++j)
                    link(id[i - 1][j][1], id[i][j][0], FastIn());
        }
        for (R int i = 1; i < n; ++i)
        {
            link(s, id[i][1][1], FastIn());
            for (R int j = 2; j < m; ++j)
                link(id[i][j - 1][0], id[i][j][1], FastIn());
            link(id[i][m - 1][0], t, FastIn());
        }
        for (R int i = 1; i < n; ++i)
            for (R int j = 1; j < m; ++j)
                link(id[i][j][0], id[i][j][1], FastIn());
        q.push(s);
        memset(d, 63, sizeof(d));
        d[s] = 0;
        while (!q.empty())
        {
            R int now = q.front(); q.pop(); vis[now] = 0;
            for (R Edge *iter = last[now]; iter; iter = iter -> next)
            {
                R int pre = iter -> to;
                if (d[pre] > d[now] + iter -> w)
                {
                    d[pre] = d[now] + iter -> w;
                    if (!vis[pre])
                    {
                        q.push(pre);
                        vis[pre] = 1;
                    }
                }
            }
        }
        printf("%d
    ", d[t] );
        return 0;
    }
    /*
    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
    */

    题外话:这里是我写的两种方法的运行时间比较:
    2016.02.23
    2016.05.17
    因为是网格图,所以SPFA跑得很慢,然而我蒟蒻还不(lan)会(de)写堆优化dij,所以这对偶了是等于没有对偶╮(╯▽╰)╭

  • 相关阅读:
    php 请求另一个服务器接口返回数据
    yii2 安装
    无限分类的
    程序员学习能力提升三要素转载
    为什么有的人工作多年还是老样子
    随笔杂谈
    Ecshop商品描述上传中文名图片无法显示解决方法
    「PSR 规范」PSR-2 编码风格规范
    leetcode 之Set Matrix Zeroes(10)
    leetcode 之Plus One(9)
  • 原文地址:https://www.cnblogs.com/cocottt/p/5550958.html
Copyright © 2020-2023  润新知