POJ 2195 GOING HOME

For each H, each m number, then traverse each m, use BFS to find the shortest distance from the m to each H, then add the edge to the graph, the super source point, the super sink point, the capacity is 1, the cost is 0, and the minimum cost flow is run once. 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int MAXN = 10000;
const int MAXM = 100000;
const int INF = 99999999;
char ma[150][150];
int used[150][150];
int no[150][150];
int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
int n, m;
struct Edge {
    int to, next, cap, flow, cost;
} edge [MAXM];
int head[MAXN], tol;
int pre[MAXN], dis[MAXN];
bool vis[MAXN];
int N;
void init(int n) {
    N = n;
    toll = 0;
    memset(head, -1, sizeof(head));
}
void addedge(int u, int v, int cap, int cost)
{
    edge[tol].to = v;
    edge [tol] .cap = cap;
    edge[tol].cost = cost;
    edge[tol].flow = 0;
    edge[tol].next = head[u];
    head[u] = tol++;
    edge[tol].to = u;
    edge[tol].cap = 0;
    edge[tol].cost = -cost;
    edge[tol].flow = 0;
    edge[tol].next = head[v];
    head[v] = tol++;
}

bool spfa(int s, int t)
{
    queue<int >q;
    for(int i = 0; i < N; i++)
    {
        dis[i] = INF;
        show [i] = 0;
        pre[i] = -1;
    }
    dis[s] = 0;
    vis [s] = 1;
    q.push(s);
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        vis [u] = 0;
        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].to;
            if (edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost)
            {
                dis[v] = dis[u] + edge[i].cost;
                for [v] = i;
                if (!vis[v])
                {
                    force[v] = 1;
                    q.push(v);
                }
            }
        }
    }
    if (pre[t] == -1) return 0;
    else return 1;
}

int mincostmaxflow(int s, int t, int &cost)
{
    int flow = 0;
    cost = 0;
    while(spfa(s, t))
    {
        int Min = INF;
        for(int i = pre[t]; i != -1; i = pre[edge[i^1].to])
        {
            if (Min > edge[i].cap - edge[i].flow)
                Min = edge[i].cap - edge[i].flow;
        }
        for(int i = pre[t]; i != -1; i = pre[edge[i^1].to])
        {
            edge[i].flow += Min;
            edge[i^1].flow -= Min;
            cost += edge[i].cost * Min;
        }
        flow += Min;
    }
    return flow;
}
struct Node {
    int x, y, w;
};
void bfsma(int x, int y)
{
    memset(used, 0, sizeof(used));
    queue<Node> q;
    Node now;
    now.x = x;
    now.y = y;
    now.w = 0;
    q.push(now);
    used[now.x][now.y] = 1;

    while(!q.empty())
    {
        now = q.front();
        q.pop();
        Node next;
        for(int i = 0; i < 4; i++)
        {
            next.x = now.x + dir[i][0];
            next.y = now.y + dir[i][1];
            next.w = now.w + 1;
            if (next.x >= n || next.y >= m || next.x < 0 || next.y < 0)
                continue;
            if (used[next.x][next.y])
                continue;
            used[next.x][next.y] = 1;
            q.push(next);
        }
        if (ma[now.x][now.y] == 'H')
        {
            //printf("%d %d %d\n", no[x][y], no[now.x][now.y], now.w);
            addedge(no[x][y], no[now.x][now.y], 1 , now.w);
        }
    }
}
intmain()
{

    while(scanf("%d%d", &n, &m) != EOF && n != 0 && m !=  0)
    {
        int years;
        int sp, tp;
        init(2000);
        for(int i = 0; i < n; i++)
        {
            scanf("%s", ma[i]);
        }
        memset(used, 0, sizeof(used));
        memset(no, 0, sizeof(no));
        int mc = 1;
        int hc = 1001;
        sp = 0;
        tp = 2000-1;
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < m; j++)
            {
                    if (ma[i][j] == 'm')
                    {
                        no[i][j] = mc++;
                    }
                    if (ma[i][j] == 'H'){
                        no[i][j] = hc++;
                        addedge(no[i][j], tp, 1, 0);
                    }
            }
        }

        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < m; j++)
            {
                    if (ma[i][j] == 'm')
                    {
                        addedge(sp, no[i][j], 1, 0);//printf("debug");
                        bfsma(i, j);
                    }
            }
        }
        mincostmaxflow(sp, tp, ans);
        cout<<ans<<endl;

    }
    return 0;
}

  

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324963847&siteId=291194637