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

来源:互联网 发布:ug8.0编程教程百度网盘 编辑:程序博客网 时间:2024/05/10 11:16
题意:

给出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 0x3f3f3f3fusing 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<=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;}


0 0