HDU-2195-Going Home

来源:互联网 发布:安广网络明光营业厅 编辑:程序博客网 时间:2024/05/20 18:48

HDU-2195-Going Home

http://acm.hdu.edu.cn/showproblem.php?pid=1533

之前用最小费用最大流做的,今天看了最大带权匹配的KM算法,套用了模板来做这题,将所有的H作为X集合,所有的m作为Y集合,构造二分图求最大带权匹配

#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>using namespace std;const int MAXN=5000;const int INF=0x7fffffff;int nx, ny, w[MAXN][MAXN], lx[MAXN], ly[MAXN];int fx[MAXN], fy[MAXN], matx[MAXN], maty[MAXN];char map[MAXN][MAXN];int n1,n2;struct node{int x;int y;}h[MAXN],man[MAXN];//模板//  Name: PerfectMatch by Kuhn_Munkras O(n^3)//  Description: w is the adjacency matrix, nx,ny are the size of x and y,//  lx, ly are the lables of x and y, fx[i], fy[i] is used for marking//  whether the i-th node is visited,  matx[x] means x match matx[x],//  maty[y] means y match maty[y], actually, matx[x] is useless,//  all the arrays are start at 1int path(int u){      fx[u] = 1;    for (int v = 1; v <= ny; v++)     if (lx[u] + ly[v] == w[u][v] && fy[v] < 0)    {               fy[v] = 1;            if (maty[v] < 0 || path(maty[v]))            {                    matx[u] = v;                    maty[v] = u;                    return 1;               }     }     return 0;}int km(){      int i,j,k,ret = 0;    memset(ly, 0, sizeof(ly));    for (i = 1; i <= nx; i++)    {          lx[i] = -INF;        for (j = 1; j <= ny; j++)         if (w[i][j] > lx[i]) lx[i] = w[i][j];    }    memset(matx, -1, sizeof(matx));    memset(maty, -1, sizeof(maty));    for (i = 1; i <= nx; i++)    {           memset(fx, -1, sizeof(fx));        memset(fy, -1, sizeof(fy));        if (!path(i))        {              i--;               int p = INF;            for (k = 1; k <= nx; k++){                if (fx[k] > 0)                for (j = 1; j <= ny; j++)                 if (fy[j] < 0 && lx[k] + ly[j] - w[k][j] < p)                p=lx[k]+ly[j]-w[k][j];            }            for (j = 1; j <= ny; j++)             ly[j] += fy[j]<0 ? 0 : p;            for (j = 1; j <= nx; j++)             lx[j] -= fx[j]<0 ? 0 : p;        }    }    for (i = 1; i <= ny; i++)ret += w[maty[i]][i];    return ret;} void init(){int i,j,v;char c;nx=ny=0;for(i=0;i<n1;i++){for(j=0;j<n2;j++){scanf("%c",&c);if(c=='H'){h[++nx].x=i;h[nx].y=j;}else if(c=='m'){man[++ny].x=i;man[ny].y=j;}}getchar();}for(i=1;i<=nx;i++)for(j=1;j<=ny;j++)w[i][j]=-99999999;for(i=1;i<=nx;i++)for(j=1;j<=ny;j++)w[i][j]=-(abs(h[i].x-man[j].x)+abs(h[i].y-man[j].y)); }int main(){while(scanf("%d %d",&n1,&n2),n1||n2){getchar();init();printf("%d\n",-km());}return 0;}


原创粉丝点击