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的主要内容,如果未能解决你的问题,请参考以下文章
Going Home POJ - 2195 (最小费用最大流)