您的位置:首页 > 编程语言 > Go语言

HDU1533||ZQUOJ23130Going Home最小费用最大流

2016-07-13 13:32 295 查看
题意:

给出NxM的地图,'.'表示可以走的,'H'表示家,'m'表示人,H和m的数目相同,

求把所有人移动到H的最小步数

解题思路:  建立超级源点,分别连接每个m,容量为1,费用0

                 建立超级汇点,分别把每个H连接到汇点,容量为1,费用为0

                 再把每个m分别指向H,容量为1,费用为该m到H的横纵左边之差的绝对值的和,|X1-X2|+|Y1-Y2|
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define w 0x3f3f3f3f
using namespace std;
const int r=205;
struct s1{
int x,y;
}A[r],B[r];
int T,W,pre[r],a[r],b[r],path[r],map[r][r],value[r][r];
struct s2{
int to,next,f;
}edg[60000];
int fab(int x)
{
return (x<0)?-x:x;
}
void add(int i,int j,int k)
{
edg[T].to=j;
edg[T].f=k;
edg[T].next=pre[i];
pre[i]=T++;
value[i][j]=k;
}
queue<int>q;
int spfa()
{
memset(path,-1,sizeof(path));
memset(a,w,sizeof(a));
memset(b,0,sizeof(b));
q.push(0);
a[0]=0;
b[0]=1;
int i,j,k,t;
while(!q.empty())
{
t=q.front();
q.pop();
b[t]=0;
for(j=pre[t];j!=-1;j=edg[j].next)
{
k=edg[j].to;
if(map[t][k]>0&&(a[k]==w||a[k]>a[t]+edg[j].f))
{
a[k]=a[t]+edg[j].f;
path[k]=t;
if(!b[k])
{
b[k]=1;
q.push(k);
}
}
}
}

return a[W]==w?0:1;
}

int EK()
{
int i,j,k=w,sum=0;
for(i=W;i!=-1;i=path[i])
{
if(path[i]!=-1)
k=min(k,map[path[i]][i]);
}
for(i=W;i!=-1;i=path[i])
{
if(path[i]!=-1)
{
map[path[i]][i]-=k;
map[i][path[i]]+=k;
sum+=value[path[i]][i];
}
}
return sum;
}

int slove()
{
int m=0;
while(spfa())
m+=EK();
return m;
}
int main()
{
int n,m,i,j,k,t;
char str[r][r];
while(~scanf("%d%d",&n,&m)&&n+m)
{
memset(pre,-1,sizeof(pre));
memset(map,0,sizeof(map));
memset(value,0,sizeof(value));
T=0,t=0,k=0;
for(i=0;i<n;i++)
{
scanf("%s",str[i]);
for(j=0;j<m;j++)
{
if(str[i][j]=='H')
{
A[t].x=i;
A[t++].y=j;
}
if(str[i][j]=='m')
{
B[k].x=i;
B[k++].y=j;
}
}
}
W=t+t+1;
for(i=1;i&
a5bf
lt;=t;i++)
{
add(0,i,0);
map[0][i]=1;
add(i,0,0);
for(j=1;j<=t;j++)
{
k=fab(A[i-1].x-B[j-1].x)+fab(A[i-1].y-B[j-1].y);
add(i,j+t,k);
map[i][j+t]=1;
add(j+t,i,-k);
}
add(i+t,W,0);
map[i+t][W]=1;
add(W,i+t,0);
}
printf("%d\n",slove());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: