HDU - 1533 - Going Home (一般费用流)

http://acm.hdu.edu.cn/showproblem.php?pid=1533

题意:

有n个人n个房子,每一人移动一格都需要1花费,问最小花费是多少

思路:

一个裸的最小费最大流,可参考模版这里

#include <iostream>
#include <string.h>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <stdio.h>
#include <deque>

using namespace std;

#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define maxn 1000005
#define eps 0.00000001
#define PI acos(-1.0)
#define M 1000000007

struct Edge {
    int v, w, nxt, cost, sy;
}edge[maxn];

char MP[maxn/100][maxn/100];
int head[maxn/10], dis[maxn/10], vis[maxn/10], pre[maxn/10], tot;
int S, T, n, m;

void init() {
    tot = 0;
    T = n * m + 1;
    S = 0;
    memset(head, -1, sizeof(head));
}

void addEdge(int u, int v, int w, int cost) {
    edge[tot].v = v;
    edge[tot].w = w;
    edge[tot].sy = 0;
    edge[tot].cost = cost;
    edge[tot].nxt = head[u];
    head[u] = tot ++;

    edge[tot].v = u;
    edge[tot].w = 0;
    edge[tot].sy = 0;
    edge[tot].cost = -cost;
    edge[tot].nxt = head[v];
    head[v] = tot ++;
}

bool SPFA() {
    memset(dis, INF, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    memset(pre, -1, sizeof(pre));
    queue<int> que;
    que.push(S);
    dis[S] = 0;
    vis[S] = 1;
    pre[S] = -1;
    while(!que.empty()) {
        int u = que.front(); que.pop();
        vis[u] = 0;
        for (int i = head[u]; i + 1; i = edge[i].nxt) {
            if(dis[edge[i].v] > dis[u] + edge[i].cost && edge[i].w > edge[i].sy) {
                dis[edge[i].v] = dis[u] + edge[i].cost;
                pre[edge[i].v] = i;
                if(!vis[edge[i].v]) {
                    vis[edge[i].v] = 1;
                    que.push(edge[i].v);
                }
            }
        }
    }
    if(pre[T] == -1)
        return 0;
    return 1;
}

int MinCostMaxFlow(int &Cost) {
    int Flow = 0, MinCost = INF;
    Cost = 0;
    while(SPFA()) {
        for (int i = pre[T]; i + 1; i = pre[edge[i ^ 1].v])
            MinCost = min(MinCost, edge[i].w - edge[i].sy);//最小流量
        for (int i = pre[T]; i + 1; i = pre[edge[i ^ 1].v]) {
            edge[i].sy += MinCost;
            edge[i ^ 1].sy -= MinCost;
            Cost += edge[i].cost * MinCost;//费用= sigma每条路线的最小流量*花费
        }
        Flow += MinCost;
    }
    return Flow;
}


int main(int argc, const char * argv[]) {
    while(scanf("%d %d",&n, &m) && (n || m)) {
        init();
        for (int i = 1; i <= n; i ++) {
            getchar();
            scanf("%s", MP[i]);
        }
        for (int i = 1; i <= n; i ++) {
            for (int j = 1; j <= m; j ++) {
                if(MP[i][j - 1] == '.') continue;
                if(MP[i][j - 1] == 'm') {
                    addEdge(S, (i - 1) * m + j, 1, 0);
                    for (int k = 1; k <= n; k ++)
                        for (int z = 1; z <= m; z ++)
                            if(MP[k][z - 1] == 'H')
                                addEdge((i - 1) * m + j, (k - 1) * m + z, 1, abs(i - k) + abs(j - z));
                }
                else
                    addEdge((i - 1) * m + j, T, 1, 0);
            }
        }
        int ans = 0;
        MinCostMaxFlow(ans);
        printf("%d\n", ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/henu_jizhideqingwa/article/details/81980503