码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 2195 GOING HOME

时间:2018-04-27 19:53:47      阅读:149      评论:0      收藏:0      [点我收藏+]

标签:超级   cap   dde   include   return   scan   push   tin   home   

对于每一个H 每一个m编号 然后遍历每一个m 使用BFS求出该m到每一个H的最短距离 然后把边加进图里 超级源点 超级汇点 容量为1 费用为0 跑一遍最小费用流 

#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;
    tol = 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;
        vis[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;
                pre[v] = i;
                if (!vis[v])
                {
                    vis[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);
        }
    }
}
int main()
{

    while(scanf("%d%d", &n, &m) != EOF && n != 0 && m !=  0)
    {
        int ans;
        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;
}

  

POJ 2195 GOING HOME

标签:超级   cap   dde   include   return   scan   push   tin   home   

原文地址:https://www.cnblogs.com/16-CHQ/p/8963536.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!