Poj 2195 Going Home

Posted nldqy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Poj 2195 Going Home相关的知识,希望对你有一定的参考价值。

题目链接:ヾ(≧?≦*)ゝ

题意:有n*m的矩阵,H表示这个点是一个房子,m表示这个点是一个人,现在每一个人需要走入一个房间,已经知道的是
认得数目和房子的个数一定是相同的,现在问这些人都回到一个房间所走的总的步数最小

Solution:

(2le nle100,2le mle100),费用流

把所有的人和房子连边,容量为1,费用为需要的步数

把源点与人连边,容量为1,费用为0,汇点与房子连边,容量为1,费用为0

需要解释的是为什么汇点与房子连的边容量为1,这是因为每个房子只能住一个人

最后一遍费用流得出答案。本题有多组数据,读入到0结束。

Code:

#include<queue>
#include<cstdio>
#include<ctype.h>
#include<cstring>
#include<algorithm>
#define N 50001
#define inf 1926081700
using namespace std;
typedef pair<int,int> pii;
int n,m,cnt=1,t;
int S,T,head[N],per[N];
char mp[101][101];
struct Edge{int nxt,to,v,w;}edge[N];
void ins(int x,int y,int z,int w){
    edge[++cnt].nxt=head[x];
    edge[cnt].to=y;edge[cnt].v=z;
    edge[cnt].w=w;head[x]=cnt;
}
namespace Network_Flow{
    queue<int> q;
    int delta,maxflow,mincost;
    int vis[N],pre[N],dis[N];
    int spfa(){
        delta=inf;pre[T]=0;
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=T;i++) dis[i]=inf;
        q.push(S);vis[S]=1;dis[S]=0;
        while(!q.empty()){
            int x=q.front();q.pop();vis[x]=0;
            for(int i=head[x];i;i=edge[i].nxt){
                int y=edge[i].to;
                if(edge[i].v&&dis[x]+edge[i].w<dis[y]){
                    dis[y]=edge[i].w+dis[x];
                    delta=min(delta,edge[i].v);
                    pre[y]=i;if(!vis[y]) q.push(y),vis[y]=1;
                }
            }
        }
        return pre[T];
    }
    void update(){
        int x=T;
        while(x!=S){
            int u=pre[x];
            edge[u].v-=delta;
            edge[u^1].v+=delta;
            x=edge[u^1].to;
        }
        maxflow+=delta;mincost+=dis[T];
    }
    void Edmonds_Karp(){
        mincost=maxflow=0;
        while(spfa()) update();
        printf("%d
",mincost);
    }
}
void format(){
    cnt=1;t=0;
    memset(head,0,sizeof(head));
    memset(edge,0,sizeof(edge));
}
int num(int i,int j){return (i-1)*m+j;}
pii pos(int x){return make_pair(x/m+(x%m!=0),(x%m==0)?m:x%m);}
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
int main(){
    using namespace Network_Flow;
    begin:n=read();m=read();
    if(n==0||m==0) return 0;
    S=n*m+1;T=S+1;format();
    for(int i=1;i<=n;i++)
        scanf("%s",mp[i]+1);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(mp[i][j]=='m'){
                int x=num(i,j);
                per[++t]=num(i,j);
                ins(S,x,1,0);ins(x,S,0,0);
            }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(mp[i][j]=='H'){
                int x=num(i,j);
                for(int k=1;k<=t;k++){
                    pii tmp=pos(per[k]);
                    int w=abs(tmp.first-i)+abs(tmp.second-j);
                    ins(per[k],x,1,w);ins(x,per[k],0,-w);
                }
                ins(x,T,1,0);ins(T,x,0,0);
            }
    Edmonds_Karp();goto begin;
}

以上是关于Poj 2195 Going Home的主要内容,如果未能解决你的问题,请参考以下文章

POJ2195 Going Home

POJ2195:Going Home——题解

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

D - Going Home POJ - 2195 网络流

POJ 2195 - Going Home - [最小费用最大流][MCMF模板]

POJ 2195 Going Home(KM算法求最小权匹配)