POJ 2195 最小费用流

点击打开链接

题意:给个乱七八糟的方阵,H代表家,m代表人,现在所有人都要回到一个家,问所有人走到家的步数和

思路:还是很好想到费用流的,费用为人走到家的步数,求最小,流量即为人的个数,连边的话,每个人都连到家的容量为1,费用为步数的边,建立超级源点与人相连,容量为1,费用为0,家与超级汇点相连,一样容量为1肥育馆为0,跑最小费用流就是结果了,PS:入门题,还是蛮简单的.........

#include <queue>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=10010;
typedef pair<int,int> P;
struct edge{
    int to,cap,cost,rev;
    edge();
    edge(int a,int b,int c,int d){to=a,cap=b,cost=c,rev=d;};
};
vector<edge>G[maxn];
int h[maxn],dis[maxn],prevv[maxn],preve[maxn];
void addedge(int st,int en,int cap,int cost){
    G[st].push_back(edge(en,cap,cost,G[en].size()));
    G[en].push_back(edge(st,0,-cost,G[st].size()-1));
}
int min_cost_flow(int st,int en,int f){
    int ans=0;
    memset(h,0,sizeof(h));
    while(f>0){
        priority_queue<P,vector<P>,greater<P> >que;
        memset(dis,inf,sizeof(dis));
        dis[st]=0;que.push(P(0,st));
        while(!que.empty()){
            P p=que.top();que.pop();
            int v=p.second;
            if(dis[v]<p.first) continue;
            for(unsigned int i=0;i<G[v].size();i++){
                edge &e=G[v][i];
                if(e.cap>0&&dis[e.to]>dis[v]+e.cost+h[v]-h[e.to]){
                    dis[e.to]=dis[v]+e.cost+h[v]-h[e.to];
                    prevv[e.to]=v;
                    preve[e.to]=i;
                    que.push(P(dis[e.to],e.to));
                }
            }
        }
        if(dis[en]==inf) return -1;
        for(int i=0;i<maxn;i++) h[i]+=dis[i];
        int d=f;
        for(int i=en;i!=st;i=prevv[i]){
            d=min(d,G[prevv[i]][preve[i]].cap);
        }
        f-=d;
        ans+=d*h[en];
        for(int i=en;i!=st;i=prevv[i]){
            edge &e=G[prevv[i]][preve[i]];
            e.cap-=d;
            G[i][e.rev].cap+=d;
        }
    }
    return ans;
}
int num1[110][2],num2[110][2];
int main(){
    int n,m;
    char str[110][110];
    while(scanf("%d%d",&n,&m)!=-1){
        if(n==0&&m==0) break;
        memset(num1,0,sizeof(num1));
        memset(num2,0,sizeof(num2));
        for(int i=0;i<maxn;i++) G[i].clear();
        for(int i=0;i<n;i++) scanf("%s",str[i]);
        int k1=0,k2=0;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(str[i][j]=='m'){
                    num1[k1][0]=i;num1[k1++][1]=j;
                }else if(str[i][j]=='H'){
                    num2[k2][0]=i;num2[k2++][1]=j;
                }
            }
        }
        for(int i=1;i<=k1;i++) addedge(0,i,1,0);
        for(int i=k1+1;i<=k1+k2;i++) addedge(i,k1+k2+1,1,0);
        for(int i=0;i<k1;i++){
            for(int j=0;j<k2;j++){
                int t=abs(num2[j][0]-num1[i][0])+abs(num2[j][1]-num1[i][1]);
                addedge(i+1,j+k1+1,1,t);
            }
        }
        printf("%d\n",min_cost_flow(0,k1+k2+1,k1));
    }
    return 0;
}
时间: 2024-10-07 13:04:54

POJ 2195 最小费用流的相关文章

POJ 2195 Going Home【最小费用流 二分图最优匹配】

题目大意:一个n*m的地图,上面有一些人man(m)和数量相等的house(H) 图上的距离为曼哈顿距离 问所有人住进一所房子(当然一个人住一间咯)距离之和最短是多少? 思路:一个人一间房,明显是二分图的模型,边权为人和房子的曼哈顿距离,然后算一下最小距离即可 懒得学KM了 最小费用流的经典建图 #include #include #include #include #include #define maxn 40000 #define inf 0x3f3f3f3f using namespac

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 2195 Going Home / HDU 1533(最小费用最大流模板)

题目大意: 有一个最大是100 * 100 的网格图,上面有 s 个 房子和人,人每移动一个格子花费1的代价,求最小代价让所有的人都进入一个房子.每个房子只能进入一个人. 算法讨论: 注意是KM 和 MCMF算法,我写的是MCMF算法,一开始想的是连10000个点,但是不会连那些大众点之间的边,只会连超级点和普通点之间的边.后来觉得只要连房子点和 人点就可以了.连从人到房子的边,容量是1,花费是他们之间的曼哈顿距离,然后超级源点和超级汇点像上面那样连接,注意连点的时候把他们每个点都具体化一下,就

poj 2195 Going Home 二分图最小权匹配KM算法

题意: 有n个人要回到n间房子里,每间房子只允许一个人,求n个人要走的最小距离和. 分析: 裸的二分图最小权匹配,KM搞之. 代码: //poj 2195 //sep9 #include <iostream> using namespace std; const int maxN=128; char g[maxN][maxN]; int mx[maxN],my[maxN],hx[maxN],hy[maxN]; int w[maxN][maxN]; int lx[maxN],ly[maxN],l

POJ 2195 Going Home (最小费用最大流)

题目链接:http://poj.org/problem?id=2195 题意:n*m的矩阵,地图上有若干个人(m)和房子(H),且人与房子的数量一致.man每移动一格费用为1,一个房子只能住一个人.现在要求所有的人出发,都入住房子,求最少话费. 思路:建立一个超级源点和汇点,源点与人相连费用为0,容量为1,人与房子相连,费用为人与房子的距离,容量为1,房子与汇点相连,费用为0,容量为1 #include <iostream> #include <cstdlib> #include

POJ 2516 最小费用流

依然最小费用最大流模板题 建边麻烦了些 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <vector> #include <utility> #include <stack> #include <queue> #include <ma

POJ 2195 二分图最小权匹配KM算法

本来是打算昨天晚上写的, 昨天网速渣的连CSDN都进不去,没办法 只能现在来写了 先写写对KM算法的理解,KM算法是对每个点设置一个顶标,只有当边长等于两边点的顶标之和的时候才进行增广,这样就能保证得到的一定是最大权匹配. 如果找不到匹配的时候就对交替路中X集合的顶标减少一个d Y集合的顶标增加一个d. 这样两个点都在交替路中的时候x[i]+y[i]的和不边 X在 Y不在的时候x[i]+y[i]减少,可能就会为图增加一对匹配. X不在Y在的时候x[i]+y[i]增加, 原来不在现在依然不在其中.

POJ 2195 Going Home 最小费用最大流 尼玛,心累

D - Going Home Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 2195 Appoint description: Description On a grid map there are n little men and n houses. In each unit time, every little man can mo

poj 2195 Going Home(最小费最大流)

poj 2195 Going Home 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