BZOJ1001 洛谷4001 [BJOI2006]狼抓兔子 题解

题目

这个题目有多种解法,这个题也是一个比较经典的题了,正是因为他的多样的做法,这个题主要难在建图和优化,因为这是一个网格图,所以spfa肯定过不去,所以用最短路解法的话,只能用dij,而网络流也是要加上几个必不可少的优化,具体在代码中解释:

代码:

// luogu-judger-enable-o2
#include <bits/stdc++.h>
#define M 6000100
#define N 200100
#define inf 1 << 30
using namespace std;
queue <int> q;
struct cym {
    int to, next, len;
}e[M * 2];
int lin[M * 2], cnt = 1;
int n, m, s, t, deep[M];
inline void add(int u, int v, int w)
{
    e[++cnt].to = v;
    e[cnt].len = w;
    e[cnt].next = lin[u];
    lin[u] = cnt;
}
inline bool bfs()
{
    int i, now;
    memset(deep, 0 ,sizeof(deep));
    q.push(s);
    deep[s] = 1;
    while(!q.empty())
    {
        int now = q.front();
        q.pop();
        for(int i = lin[now]; i; i = e[i].next)
        {
            if(e[i].len && !deep[e[i].to])
            {
                deep[e[i].to] = deep[now] + 1;
                q.push(e[i].to);
            }
        }
    }
    if(deep[t] > 0)
        return 1;    
    return 0;
}
int dfs(int x, int maxflow)//maxflow是当前最多可以流多少流量
{
    if(x == t || maxflow == 0)
        return maxflow;
    int w, used = 0;
    for(int i = lin[x]; i; i = e[i].next)
    {
        if(deep[e[i].to] == deep[x] + 1 && e[i].len)
        {
            w = dfs(e[i].to, min(maxflow - used, e[i].len));//w=这条边权的最小值或当前最多可以流的流量减去当前增广的流量
            if(!w)//如果当前不能走了,就把这条路封掉,封掉的方法就是把层数设为0
            {
                deep[e[i].to] = 0;
                continue;
            }
            used += w;//当前可以流的流量
            e[i].len -= w;
            e[i ^ 1].len += w;
            if(used == maxflow)//相当于当前用光了 ,没有可以增广的流量了
                return used; 
        }
    }
    if(!used)//used 是现在可以增广的流量        
        deep[x] = 0;
    return used;
}
int dinic()
{
    int ans = 0;
    while(bfs())
    {
        ans += dfs(s, inf);
    }
    return ans;
}
inline int read() {
    char ch = getchar(); int x = 0, f = 1;
    while(ch < '0' || ch > '9') {
        if(ch == '-') f = -1;
        ch = getchar();
    } while('0' <= ch && ch <= '9') {
        x = x * 10 + ch - '0';
        ch = getchar();
    } return x * f;
}
int main()
{
    n = read(), m = read();
    s = 1, t = n * m;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j < m; j++)
        {
            int w;
            w = read();
            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;
            w = read();
            add ( (i - 1) * m + j, (i - 1) * m + j + m, w);
            add ( (i - 1) * m + j + m, (i - 1) * m + j, w);
        }
    for (int i = 1; i < n; i++)
        for (int j = 1; j < m; j++)
        {
            int w;
            w = read();
            add ( (i - 1) * m + j, (i - 1) * m + j + m + 1, w);
            add ( (i - 1) * m + j + m + 1, (i - 1) * m + j, w);
        }
    /*
    for(int i = 1; i <= cnt; i++)
    {
        printf("%d %d %d\n", e[i].to, e[i].len, e[i].next);
    }*/
    printf("%d", dinic());
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/liuwenyao/p/9437534.html