POJ训练计划2195_Going Home(网络流/费用流)

解题报告

题目传送门

思路:

bfs建图跑一下费用流就行。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define inf 0x3f3f3f3f

using namespace std;
struct E {
    int v,cost,cap,next;
} edge[100000];
int head[1000],cnt,dis[1000],pre[1000],vis[1000],s,t,mmap[110][110],h,w,f[1100],cost,flow;
struct N {
    int x,y,step;
};
void add(int u,int v,int cost,int cap) {
    edge[cnt].v=v;
    edge[cnt].cost=cost;
    edge[cnt].cap=cap;
    edge[cnt].next=head[u];
    head[u]=cnt++;

    edge[cnt].v=u;
    edge[cnt].cost=-cost;
    edge[cnt].cap=0;
    edge[cnt].next=head[v];
    head[v]=cnt++;
}
int dx[]= {-1,0,1,0};
int dy[]= {0,1,0,-1};
void bfs(int x,int y) {
    queue<N>q;
    int v[110][110];
    memset(v,0,sizeof(v));
    N next,now;
    now.x=x;
    now.y=y;
    now.step=0;
    v[x][y]=1;
    q.push(now);
    while(!q.empty()) {
        now=q.front();
        q.pop();
        if(mmap[now.x][now.y]>=101) {
            add(mmap[x][y],mmap[now.x][now.y],now.step,1);
        }
        for(int i=0; i<4; i++) {
            next.x=now.x+dx[i];
            next.y=now.y+dy[i];
            if(next.x>=0&&next.x<h&&next.y>=0&&next.y<w&&!v[next.x][next.y]) {
                next.step=now.step+1;
                v[next.x][next.y]=1;
                q.push(next);
            }
        }
    }
}
int _spfa() {
    for(int i=0; i<=201; i++) {
        dis[i]=inf;
        vis[i]=pre[i]=f[i]=0;
    }
    dis[s]=0;
    vis[s]=1;
    pre[s]=-1;
    f[s]=inf;
    queue<int>Q;
    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].v;
            if(edge[i].cap&&dis[v]>dis[u]+edge[i].cost) {
                pre[v]=i;
                dis[v]=dis[u]+edge[i].cost;
                f[v]=min(f[u],edge[i].cap);
                if(!vis[v]) {
                    vis[v]=1;
                    Q.push(v);
                }
            }
        }
    }
    if(dis[t]==inf)return 0;
    flow+=f[t];
    cost+=f[t]*dis[t];
    for(int i=pre[t]; i!=-1; i=pre[edge[i^1].v]) {
        edge[i].cap-=f[t];
        edge[i^1].cap+=f[t];
    }
    return 1;
}
void mcmf() {
    cost=flow=0;
    while(_spfa());
    printf("%d\n",cost);
}
int main() {
    int i,j,n,m;
    char str[1000];
    while(~scanf("%d%d",&h,&w)) {
        n=101,m=1;
        s=0,t=201;
        if(!h&&!w)break;
        memset(edge,0,sizeof(edge));
        memset(head,-1,sizeof(head));
        cnt=0;
        for(i=0; i<h; i++) {
            scanf("%s",str);
            for(j=0; j<w; j++) {
                if(str[j]=='.')
                    mmap[i][j]=-1;
                else if(str[j]=='H')
                    mmap[i][j]=n++;
                else if(str[j]=='m')
                    mmap[i][j]=m++;
            }
        }
        for(i=0; i<h; i++) {
            for(j=0; j<w; j++) {
                if(mmap[i][j]>=1&&mmap[i][j]<=100) {
                    add(0,mmap[i][j],0,1);
                    bfs(i,j);
                }
                if(mmap[i][j]>=101)
                    add(mmap[i][j],t,0,1);
            }
        }
        mcmf();
    }
    return 0;
}

Going Home

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 18017   Accepted: 9185

Description

On a grid map there are n little men and n houses. In each unit time, every little man can move one unit step, either horizontally, or vertically, to an adjacent point. For each little man, you need to pay a $1 travel fee for every step he moves, until he enters
a house. The task is complicated with the restriction that each house can accommodate only one little man.

Your task is to compute the minimum amount of money you need to pay in order to send these n little men into those n different houses. The input is a map of the scenario, a ‘.‘ means an empty space, an ‘H‘ represents a house on that point, and am ‘m‘ indicates
there is a little man on that point.

You can think of each point on the grid map as a quite large square, so it can hold n little men at the same time; also, it is okay if a little man steps on a grid with a house without entering that house.

Input

There are one or more test cases in the input. Each case starts with a line giving two integers N and M, where N is the number of rows of the map, and M is the number of columns. The rest of the input will be N lines describing the map. You may assume both
N and M are between 2 and 100, inclusive. There will be the same number of ‘H‘s and ‘m‘s on the map; and there will be at most 100 houses. Input will terminate with 0 0 for N and M.

Output

For each test case, output one line with the single integer, which is the minimum amount, in dollars, you need to pay.

Sample Input

2 2
.m
H.
5 5
HH..m
.....
.....
.....
mm..H
7 8
...H....
...H....
...H....
mmmHmmmm
...H....
...H....
...H....
0 0

Sample Output

2
10
28

Source

Pacific Northwest 2004

时间: 2024-11-28 20:21:17

POJ训练计划2195_Going Home(网络流/费用流)的相关文章

POJ训练计划2516_Minimum Cost(网络流/费用流)

解题报告 题意: 有n个商店,m个提供商,k种商品</span> n*k的矩阵,表示每个商店需要每个商品的数目: m*k矩阵,表示每个提供商拥有每个商品的个数 然后对于每个物品k,都有n*m的矩阵 i行j列表示 从j提供商向i商店运送一个k商品的代价是多少 判断所有的仓库能否满足所有客户的需求,如果可以,求出最少的运输总费用 思路: 建图的题,不能直接把所有信息建成图,因为n和m跟k都有关系,如果那样子建图的话,就要把k种拆成m类,每个仓库连向该仓库的第k种,然后再和n连线,有费用, 不过这样

POJ训练计划1459_Power Network(网络流最大流/Dinic)

解题报告 这题建模实在是好建,,,好贱,,, 给前向星给跪了,纯dinic的前向星竟然TLE,sad,,,回头看看优化,,, 矩阵跑过了,2A,sad,,, /************************************************************************* > File Name: PowerN.cpp > Author: _nplus > Mail: [email protected] > Time: 2014年07月19日 星期

POJ训练计划3422_Kaka&#39;s Matrix Travels(网络流/费用流)

解题报告 题目传送门 题意: 从n×n的矩阵的左上角走到右下角,每次只能向右和向下走,走到一个格子上加上格子的数,可以走k次.问最大的和是多少. 思路: 建图:每个格子掰成两个点,分别叫"出点","入点", 入点到出点间连一个容量1,费用为格子数的边,以及一个容量∞,费用0的边. 同时,一个格子的"出点"向它右.下的格子的"入点"连边,容量∞,费用0. 源点向(0,0)的入点连一个容量K的边,(N-1,N-1)的出点向汇点连一

POJ 2195 Going Home(网络流-费用流)

Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 17777   Accepted: 9059 Description On a grid map there are n little men and n houses. In each unit time, every little man can move one unit step, either horizontally, or vertical

POJ 1459 Power Network(网络流 最大流 多起点,多汇点)

Power Network Time Limit: 2000MS   Memory Limit: 32768K Total Submissions: 22987   Accepted: 12039 Description A power network consists of nodes (power stations, consumers and dispatchers) connected by power transport lines. A node u may be supplied

POJ 1273 Drainage Ditches(网络流 最大流)

Drainage Ditches Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 55893   Accepted: 21449 Description Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover patch. This means that the clover is covered by

POJ 3422 HDU 2686,3376 费用流拆点建图

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3376 http://acm.hdu.edu.cn/showproblem.php?pid=2686 http://poj.org/problem?id=3422 POJ 3422为从矩阵左上角走到右下角,最多走k次,每个格子里的数字只能算一次,后面可以重复经过,求经过的各个数字的和的最大值. 拆点,入点向出点连流量为1,费用为当前格子负值的边,向下方,右方连边,流量为k,费用为0,起点连流量为1,

POJ2135_Farm Tour(网络流/费用流)

解题报告 题目传送门 题意: 一个人有n个农场,他想从1到n去,有从n到1回来,要求路径最短,且没有走重复的路. 思路: 如果两次最短路感觉不行的,可以看成费用流,每一条路容量都是1,这样只要流量等于2就行了. 一次mcmf模版. #include <iostream> #include <cstring> #include <queue> #include <cstdio> #define inf 0x3f3f3f3f using namespace st

POJ 2195 Going Home(费用流)

http://poj.org/problem?id=2195 题意: 在一个网格地图上,有n个小人和n栋房子.在每个时间单位内,每个小人可以往水平方向或垂直方向上移动一步,走到相邻的方格中.对每个小人,每走一步需要支付1美元,直到他走入到一栋房子里.每栋房子只能容纳一个小人. 计算出让n个小人移动到n个不同的房子需要支付的最小费用. 思路: 源点和每个人相连,容量为1,费用为0. 汇点和每栋房子相连,容量为1,费用为0. 每个人和每栋房子相连,容量为1,费用为人和房子之间的距离. 这样一来,跑一