1001: [BeiJing2006]狼抓兔子[dinic网络流]

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_38081836/article/details/83513027

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

左上角点为(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


分析:我们肯定要堵住所有的通往终点的路口才行,也就是让起电与终点不连通,也就是求最小割,也就是求最大流。dinic水过。


a c   c o d e : ac\ code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define g getchar()
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define per(i, a, b) for(int i = a; i >= b; i--)
#define met(a, b) memset(a, b, sizeof(a))
const int maxn = 1e6 + 10;
const int inf = 0x3f3f3f3f;


inline int read() {
    int res = 0, f = 1;
    char ch = g;
    while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = g;}
    while(ch >= '0' && ch <= '9') {res = res * 10 + ch - '0'; ch = g;}
    return res * f;
}

int head[maxn * 6], u[maxn * 6], v[maxn * 6], w[maxn * 6], top = 0, S, T, cur[maxn], dep[maxn], Next[maxn * 6];

void init() {
    met(head, -1);
    top = 0;
}

void addEdge(int U, int V, int W) {
    //printf("%d -> %d %d\n", U, V, W);
    u[top] = U;
    v[top] = V;
    w[top] = W;
    Next[top] = head[U];
    head[U] = top++;

    u[top] = V;
    v[top] = U;
    w[top] = W;
    Next[top] = head[V];
    head[V] = top++;
}

bool BFS() {
    //cout << "BFS" << endl;
    met(dep, 0);
    queue<int> q;
    while(!q.empty()) q.pop();
    q.push(S);
    dep[S] = 1;
    while(!q.empty()) {
        int now = q.front();
        q.pop();
        for(int i = head[now]; i != -1; i = Next[i]) {
            int vv = v[i];
            if(dep[vv] == 0 && w[i] > 0) {
                dep[vv] = dep[now] + 1;
                q.push(vv);
            }
        }
    }
    if(dep[T] == 0) return 0;
    else return 1;
}

int DFS(int u, int flow) {
    if(u == T) return flow;
    for(int &i = cur[u]; i != -1; i = Next[i]) {
        if(dep[v[i]] == dep[u] + 1 && w[i] > 0) {
            //cout << flow << " "<< w[i]  << endl;
            int di = DFS(v[i], min(flow, w[i]));
            if(di > 0) {
                //cout << "DFS" << endl;
                w[i] -= di;
                //cout << w[i] << endl;
                w[i ^ 1] += di;
                return di;
            }

        }
    }
    return 0;
}

int dinic() {
    int ans = 0;
    while(BFS()) {
        for(int i = S; i <= T; i++) {
            cur[i] = head[i];
        }
        while(int d = DFS(S, inf)) {
            ans += d;
        }
        //cout << ans << endl;
    }
    return ans;
}

void input() {
    init();
    int n = read(), m = read(), cal;
    S = 1, T = n * m;
    int tot = 2;
    rep(i, 1, n) {
        rep(j, 2, m) {
            cal = read();
            addEdge(tot - 1, tot, cal);
            tot++;
        }
        tot++;
    }
    tot = m + 1;
    rep(i, 1, n - 1) {
        rep(j, 1, m) {
            cal = read();
            addEdge(tot - m, tot, cal);
            tot++;
        }
        //tot++;
    }
    tot = m + 2;
    rep(i, 1, n - 1) {
        rep(j, 1, m - 1) {
            cal = read();
            addEdge(tot - m - 1, tot, cal);

            //cout << tot - m - 1 << " " << tot <<endl;
            tot++;
        }
        tot++;
    }

    printf("%d\n", dinic());
}

int main() {
    input();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_38081836/article/details/83513027