1. 程式人生 > >2195 Going Home (網路流最小流)

2195 Going Home (網路流最小流)

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

題意:m為人的位置,H為房子的位置,找到所有人都可以進入房子的最小距離。

思路:網路流最小流模板題,先建圖,每一個人與房子的連線,超級源點與人的連線,房子與超級匯點的連線,跑一遍網路流。


#include<algorithm>
#include<string.h>
#include<stdio.h>
#include<queue>
#define inf 0x3f3f3f3f
#define FOR(a,b) for(int a=0;a<b;a++)
using namespace std;
int n,m,cut,HH,MM,head[20010];
char str[110][110];
struct dot
{
    int x,y;
} H[10010],M[10010];
struct node
{
    int to,l,v,nextt;
} A[100010];
void add(int x,int y,int l,int v)
{
    A[cut].l=l;
    A[cut].v=v;
    A[cut].to=y;
    A[cut].nextt=head[x];
    head[x]=cut++;
    A[cut].l=0;
    A[cut].v=-v;
    A[cut].to=x;
    A[cut].nextt=head[y];
    head[y]=cut++;
}
void init()
{
    cut=HH=MM=0;
    FOR(i,n)
    {
        scanf("%s",str[i]);
        FOR(j,m)
        {
            if(str[i][j]=='H')
            {
                H[++HH].x=i;
                H[HH].y=j;
            }
            if(str[i][j]=='m')
            {
                M[++MM].x=i;
                M[MM].y=j;
            }
        }
    }
    memset(head,-1,sizeof(head));
    for(int i=1; i<=MM; i++)
        for(int j=1; j<=HH; j++)
        {
            add(i,j+MM,1,abs(M[i].x-H[j].x)+abs(M[i].y-H[j].y));
        }
    for(int i=1; i<=MM; i++)
    {
        add(0,i,1,0);
    }
    for(int j=1; j<=HH; j++)
        add(j+MM,MM+HH+1,1,0);
}
int dis[20010],vis[20010],path[20010],flow[20010],dots[20010];
queue<int>q;
int spfa(int be,int to)
{
    memset(flow,0,sizeof(flow));
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    q.push(be);
    dis[be]=0;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=false;
        int k=head[u];
        while(k!=-1)
        {
            int v=A[k].to;
            if(A[k].l)
            {
                if(dis[v]>dis[u]+A[k].v)
                {
                    dis[v]=dis[u]+A[k].v;
                    path[v]=u;
                    dots[v]=k;
                    if(!vis[v])
                    {
                        q.push(v);
                        vis[v]=1;
                    }
                }
            }
            k=A[k].nextt;
        }
    }
    return dis[to]!=inf;
}
int MCMF(int be,int to)
{

    int ans=0,f=inf;
    while(spfa(be,to))
    {
        for(int i=to; i; i=path[i])
        {
            f=min(A[dots[i]].l,f);
        }
        for(int i=to; i; i=path[i])
        {
            ans+=f*A[dots[i]].v;
            A[dots[i]].l-=f;
            A[dots[i]^1].l+=f;
        }
    }
    return ans;
}
int main()
{
    while(~scanf("%d%d",&n,&m),n||m)
    {
        init();
        printf("%d\n",MCMF(0,MM+HH+1));
    }
}

相關推薦

POJ 2195-Going HomeKM演算法/費用演算法

Going Home Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 21730 Accepted: 10990 Description On a grid map there are n

2195 Going Home 網路

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 ver

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

POJ 2195 Going Home 【二分圖權值匹配】

傳送門:http://poj.org/problem?id=2195 Going Home Time Limit: 1000MS   Memory Limit: 65536K Tota

POJ 2195 Going Home費用題解

題意:給你一張圖,有k個人和k個房子,每個房子只能住一個人,每個人到某一房子的花費為曼哈頓距離,問你讓k個人怎麼走,使他們都住房子且花費最小。 思路:我們把所有人和超級源點相連,流量為1花費為0,所有房子和超級匯點相連,流量為1花費為0,然後把所有人和所有房子加邊,流量為1

POJ 2195 Going Home 費用

題目連結 第一次寫最小費用最大流 最小費用最大流相當於最短路和最大流的結合,建立了殘量圖後,費用作為距離 然後bfs遍歷源點到匯點的最小費用,用陣列記錄遍歷路徑,而後通過最大流的做法 對殘量圖進行更新,尋找路徑中的最小流量得到的就是最小費用最大流。 題

2195 Going Home 費用

Going HomeTime Limit: 1000MSMemory Limit: 65536KTotal Submissions: 24299Accepted: 12196DescriptionOn a grid map there are n little men and

Going Home網路 費用

Going Home Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 22035 Accepted: 11139 Description On a grid map there are n l

POJ 2195 Going Home權匹配、KM演算法

題目連結: POJ 2195 Going Home 題意: 給出一個r*c的矩陣,字母H代表房屋,字母m代表客人,房屋的數量和客人的數量相同。每間房只能住一個人。求這些客人全部住進客房的最少移動步數? #include <cstdio>

POJ 2195 Going Home費用

void 個人 nod const 移動 方向 push class main http://poj.org/problem?id=2195 題意: 在一個網格地圖上,有n個小人和n棟房子。在每個時間單位內,每個小人可以往水平方向或垂直方向上移動一步,走到相鄰的方格中。

【HDU4859】 海岸線網路-

Problem Description 歡迎來到珠海!由於土地資源越來越緊張,使得許多海濱城市都只能依靠填海來擴充套件市區以求發展。作為Z市的決策人,在仔細觀察了Z市地圖之後,你準備通過填充某些海域來擴充套件Z市的海岸線到最長,來吸引更多的遊客前來旅遊度假。為了簡化問題,假設地圖為一個N*M的格子,

bzoj2521 [Shoi2010]小生成樹網路

bzoj2521 [Shoi2010]最小生成樹 題意: 某一個圖可能有多種不同的最小生成樹。例如,下面圖 3中所示的都是圖 2中的無向圖的最小生成樹: Secsa想知道對於某一條無向圖中

BZOJ1001 [BeiJing2006]狼抓兔子網路

題目可以轉化為:從原圖中選出一個邊集,使得去掉它之後,(1,1)與(n,m)不通  即:以(1,1)為源,(n,m)為匯,求該圖最小割  不過由於節點過多,直接對輸入的圖求最小割的話會超時  轉化:求

2195 Going Home 構圖 大匹配KM演算法

題意: ‘.’ ,‘m’, ‘H’-> 通路, 人, 房子 讓所有人回到房子裡,使得總路徑最小 分析: 由題意可知,人與房的距離為權值,人和房子分別為x、y兩個集合,所以可以轉換成二部圖【權值最大】匹配問題,只要把路徑取【負值】,最後結果再取負即可 構圖之後直接使用

bzoj3894 文理分科網路

Description 文理分科是一件很糾結的事情!(雖然看到這個題目的人肯定都沒有糾結過) 小P所在的班級要進行文理分科。他的班級可以用一個n*m的矩陣進行描述,每個格子代表一個同學的座位。每位同學必須從文科和理科中選擇一科。同學們在選擇科目的時候會獲

洛谷 P2057 善意的投票網絡

ont c++ emp else 題意 art 自己 www. pop P2057 善意的投票 題目描述 幼兒園裏有n個小朋友打算通過投票來決定睡不睡午覺。對他們來說,這個問題並不是很重要,於是他們決定發揚謙讓精神。雖然每個人都有自己的主見,但是為了照顧一下自己朋友

BZOJ1001狼抓兔子(網路

BZOJ1001 狼抓兔子 題目描述 現在小朋友們最喜歡的”喜羊羊與灰太狼”,話說灰太狼抓羊不到,但抓兔子還是比較在行的, 而且現在的兔子還比較笨,它們只有兩個窩,現在你做為狼王,面對下面這樣一個網格的地形: 左上角點為(1,1),右下角點為(N,M

poj 1635 Subway tree systems樹的表示

需要 tps ola ack get poj systems 是不是 push Subway tree systems POJ - 1635 題目大意:給出兩串含有‘1’和‘0’的字符串,0表示向下搜索,1表示回溯,這

uva 11419 二分圖覆蓋

int name mat main return str als uva scan 二分圖最小覆蓋數=最大匹配數 建模後即可 #include<cstdio>#include<cstring>#include<algorithm>usin

2018.09.15 poj1734Sightseeing tripfloyd求

跟hdu1599差不多.。 只是需要輸出方案。 這個可以遞迴求解。 程式碼: #include<iostream> #include<cstdio> #include