poj 2195
题意:一个row*col的矩阵,m表示人,H表示房子,.表示空地,人数和房子数相等,如下图:
现在要让所有的人都进入不同的房子内,问总共最少走多少步?
代码:
#include<iostream>
#include<fstream>
#include<queue>
#include<cmath>
using namespace std;
int n,m;
struct e{
int data;
int c,f,w;
e *next;
e *op;
};
e edge[400];
int x[101],y[101],xx[101],yy[101];
int n1,n2;
int start=0,end=1;
int total;
int d[400];
int v[400];
e *path[400];
int pa[400];
int spfa(){
int i,j,k;
for(i=0;i<=total;i++)
d[i]=10000000;
memset(v,0,sizeof(v));
d[start]=0;
priority_queue<int> q;
q.push(start);
v[start]=1;
path[start]=0;
pa[start]=-1;
while(!q.empty()){
i=q.top();
v[i]=0;
q.pop();
e *p=edge[i].next;
while(p){
if(p->c>p->f&&d[p->data]>d[i]+p->w)
{
d[p->data]=d[i]+p->w;
path[p->data]=p;
pa[p->data]=i;
if(v[p->data]==0)
{
v[p->data]=1;
q.push(p->data);
}
}
p=p->next;
}
}
if(d[end]==10000000) return 0;
else
return d[end];
}
void solve(){
total=2*n1+1;
int i,j,k,s;
int w=0;
int flow=0;
while(s=spfa())
{
k=10000000;
j=end;
while(pa[j]!=-1)
{
k=min(path[j]->c-path[j]->f,k);
j=pa[j];
}
j=end;
while(pa[j]!=-1)
{
path[j]->f+=k;
path[j]->op->f=-1*path[j]->f;
j=pa[j];
}
w+=s*k;
flow+=k;
}
cout<<w<<endl;
// cout<<flow<<endl;
}
void add(int s,int t,int value,int w){
e *p=new e;
p->data=t;
p->c=value;
p->f=0;
p->w=w;
p->next=edge[s].next;
edge[s].next=p;
e *q=new e;
q->data=s;
q->c=q->f=0;
q->w=-w;
q->next=edge[t].next;
edge[t].next=q;
p->op=q;
q->op=p;
}
void read(){
// ifstream cin("in.txt");
int i,j,k;
char c;
while(cin>>n>>m)
{
if(n==0&&m==0) return ;
n1=0;
n2=0;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
cin>>c;
if(c=='H')
{
x[++n1]=i;
y[n1]=j;
}
if(c=='m')
{
xx[++n2]=i;
yy[n2]=j;
}
}
for(i=0;i<=n1*2+1;i++)
edge[i].next=0;
for(i=2;i<=n1+1;i++)
add(0,i,1,0);
for(i=n1+2;i<=n1*2+1;i++)
add(i,1,1,0);
for(i=1;i<=n1;i++)
for(j=1;j<=n2;j++)
add(i+1,j+n1+1,1,abs(x[i]-xx[j])+abs(y[i]-yy[j]));
solve();
}
}
int main(){
read();
return 0;
}
浙公网安备 33010602011771号