• BZOJ1001 狼抓兔子


    @(BZOJ)[網絡流]

    Description

    现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,
    而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:
    enter image description here
    左上角点为(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
    

    Solution

    最小割-->網絡流水題
    Dinic中的剪枝優化一定要用全. 三個優化都已經在代碼中標明.

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<climits>
    #include<algorithm>
    using namespace std;
    inline int read()
    {
        int x = 0, flag = 1;;
        char c;
        while(! isgraph(c = getchar()))
            if(c == '-')
                flag *= - 1;
        while(isgraph(c))
            x = x * 10 + c - '0', c = getchar();
        return x * flag;
    }
    void print(int x)
    {
        if(x < 0)
            putchar('-'), x *= - 1;
        if(x == 0)
            putchar('0');
        int ans[10], top = 0;
        while(x)
            ans[top ++] = x % 10, x /= 10;
        for(; top; top --)
            putchar(ans[top - 1] + '0');
    }
    const int oo = INT_MAX;
    const int MAXN = 1 << 10, MAXM = 1 << 10;
    int top;
    struct Edge
    {
        int v, flow, next;
        Edge(){}
        Edge(int v, int flow, int next): v(v), flow(flow), next(next){}
    }G[MAXN * MAXM << 3];
    int head[MAXN * MAXM];
    void add_edge(int u, int v, int flow)
    {
        G[top] = Edge(v, flow, head[u]);
        head[u] = top ++;
    }
    int Q[MAXN * MAXM];
    int dep[MAXN * MAXM];
    inline int BFS(int s, int t)
    {
        int L = 0, R = 1;
        Q[L] = s;
        memset(dep, - 1, sizeof(dep));
        dep[s] = 0;
        while(L < R)
        {
            int u = Q[L];
            for(int i = head[u]; i != - 1; i = G[i].next)
                if(dep[G[i].v] == - 1 && G[i].flow)
                {
                    dep[G[i].v] = dep[u] + 1, Q[R ++] = G[i].v;
                    if(G[i].v == t)		//優化③ 
                    	return 1;
                }
            L ++;
        }
        return 0; 
    }
    inline int DFS(int u, int flow, int t)
    {
        if(u == t)
            return flow;
        int flow_sum = 0;
        for(int i = head[u]; i != - 1; i = G[i].next)
        {
            int v = G[i].v;
            if(G[i].flow && dep[v] == dep[u] + 1)
            {
                int cur_flow = min(G[i].flow, flow - flow_sum);
                cur_flow = DFS(v, cur_flow, t);
                flow_sum += cur_flow;
                G[i].flow -= cur_flow;
                G[i ^ 1].flow += cur_flow;
                if(flow_sum == flow)	//優化②, 也是最主要的優化 
    				return flow; 
            }
        }
        if(! flow_sum)  //優化① 
            dep[u] = - 1; 
        return flow_sum;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("BZOJ1001.in", "r", stdin);
        freopen("BZOJ1001.out", "w", stdout);
        #endif
        int n = read(), m = read();
        top = 0;
        memset(head, - 1, sizeof(head));
        for(int i = 0; i < n; i ++)
            for(int j = 1; j < m; j ++)
            {
                int flow = read();
                add_edge(i * m + j, i * m + j - 1, flow),
                add_edge(i * m + j - 1, i * m + j, flow);
            }
        for(int i = 1; i < n; i ++)
            for(int j = 0; j < m; j ++)
            {
                int flow = read();
                add_edge(m * i + j, m * (i - 1) + j, flow);
                add_edge(m * (i - 1) + j, m * i + j, flow);
            }
        for(int i = 1; i < n; i ++)
            for(int j = 1; j < m; j ++)
            {
                int flow = read();
                add_edge(m * i + j, m * (i - 1) + j - 1, flow);
                add_edge(m * (i - 1) + j - 1, m * i + j, flow);
            }
        int flow = 0;
        while(BFS(0, n * m - 1))
            flow += DFS(0, oo, n * m - 1);
        print(flow);
    }
    
  • 相关阅读:
    辨析六种单例模式
    理解模板模式
    常用DOM API总结
    自我剖析——一天的效率
    对两个数组合并,并去重
    Qt 创建一个QtDesinger第三方控件
    Qt中QComboBox中自定义界面使用stylesheet实现下拉按钮独立效果
    内核对象 windows操作系统
    python之基本内容
    python之总体理解
  • 原文地址:https://www.cnblogs.com/ZeonfaiHo/p/6483013.html
Copyright © 2020-2023  润新知