uva1515_Pool construction_最大流_最小割

题目大意

给一个 h * w 的矩阵,'#' 表示草地,'.' 表示洞,草地变成洞花费d,洞变成草地花费f,在洞和草地的边缘间围栏花费b,求最小花费。

要求矩阵边缘必须是草地。

思路

矩阵中的每个单元为一个节点,节点分为两个集合S集和T集,最终与s相连的S集节点为草地,T集节点为洞。

s向原为草地的节点建容量为d的边,当此边进入最小割时,此节点进入T集,即草地变为洞,边缘草地与s建立容量未INF的边即此边不能进入割集。

同理原为洞的节点和t点建立容量为f的边。

在矩阵中相邻的节点之间建立双向的容量都为b的边,当最终相邻节点分别在S集和T集时,此边进入割集。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#define INF 0x3f3f3f3f
#define rep0(i, n) for (int i = 0; i < n; i++)
#define rep1(i, n) for (int i = 1; i <= n; i++)
#define rep_0(i, n) for (int i = n - 1; i >= 0; i--)
#define rep_1(i, n) for (int i = n; i > 0; i--)
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define mem(x, y) memset(x, y, sizeof(x))
#define MAXW 100
#define idx(x, y) ((x) * 50 + (y))
using namespace std;
typedef long long ll;
const int T = MAXW * MAXW - 1;
struct Edge
{
    int to, cap, flow, rev;
};
vector<Edge> G[MAXW * MAXW];
void addEdge(int u, int v, int cap)
{
    G[u].push_back((Edge){v, cap, 0, G[v].size()});
    G[v].push_back((Edge){u, 0, 0, G[u].size() - 1});

}

int d, f, b;
int w, h;
char g[MAXW][MAXW];
int level[MAXW * MAXW], itr[MAXW * MAXW];

void bfs()
{
    mem(level, -1);
    level[0] = 0;
    queue<int> q;
    q.push(0);

    while (!q.empty())
    {
        int u = q.front();
        q.pop();
        for (int i = 0; i < G[u].size(); i++)
        {
            Edge e = G[u][i];
            if (level[e.to] < 0 && e.cap > e.flow)
            {
                q.push(e.to);
                level[e.to] = level[u] + 1;
            }
        }
    }


}
int dfs(int u, int f)
{
    if (u == T)
        return f;

    for (int& i = itr[u]; i < G[u].size(); i++)
    {
        Edge& e = G[u][i];
        if (level[e.to] > level[u] && e.cap > e.flow)
        {
            int d = dfs(e.to, MIN(f, e.cap - e.flow));
            if (d)
            {
                e.flow += d;
                G[e.to][e.rev].flow -= d;
                return d;
            }
        }
    }
    return 0;
}
ll max_flow()
{
    ll flow = 0;

    while (true)
    {
        bfs();
        if (level[T] < 0)
            return flow;

        ll f;
        mem(itr, 0);

        while ((f = dfs(0, INF)) > 0)
        {
            flow += f;
        }
    }
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
    #endif // ONLINE_JUDGE
    int t;
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d %d", &w, &h);
        scanf("%d %d %d", &d, &f, &b);
        for (int i = 0; i < h; i++)
        {
            scanf("%s", g[i]);

        }

        for (int i = 0; i < h; i++)
            for (int j = 0; j < w; j++)
                G[i * 50 + j].clear();
        ll ans = 0;
        for (int i = 0; i < w; i++)
            if (g[0][i] == '.')
                ans += f;
        for (int i = 0; i < w; i++)
            if (g[h - 1][i] == '.')
                ans += f;
        for (int i = 1; i < h - 1; i++)
            if (g[i][0] == '.')
                ans += f;
        for (int i = 1; i < h - 1; i++)
            if (g[i][w - 1] == '.')
                ans += f;
        if (w == 2 || h == 2)
        {
            printf("%lld\n", ans);
            continue;
        }
        for (int i = 1; i < w - 1; i++)
        {
            addEdge(0, idx(0, i), INF);
            addEdge(0, idx(h - 1, i), INF);
            addEdge(idx(h - 1, i), idx(h - 2, i), b);

        }
        for (int i = 1; i < h - 1; i++)
        {
            addEdge(0, idx(i, 0), INF);
            addEdge(0, idx(i, w - 1), INF);
            addEdge(idx(i, w - 1), idx(i, w - 2), b);
        }

        for (int i = 1; i < h - 1; i++)
        {
            for (int j = 1; j < w - 1; j++)
            {
                addEdge(idx(i - 1, j), idx(i, j), b);
                addEdge(idx(i, j), idx(i - 1, j), b);
                addEdge(idx(i, j - 1), idx(i, j), b);
                addEdge(idx(i, j), idx(i, j - 1), b);
                if (g[i][j] == '#')
                {
                    addEdge(0, idx(i, j), d);

                }
                else
                {
                    addEdge(idx(i, j), T, f);

                }
            }
        }

        ans += max_flow();
        printf("%lld\n", ans);




    }




    return 0;
}

猜你喜欢

转载自blog.csdn.net/Anna__1997/article/details/81101080
今日推荐