HDU 1533 Going Home

来源:互联网 发布:淘宝动态评分计算器 编辑:程序博客网 时间:2024/06/05 10:10

HDU 1533 Going Home

题目:HDU 1533

题意:

m代表人,H代表家,将全部人安排最短的路线回家。


思路:  

将“人”与每个“家”连一条线,并且以两者的横纵坐标的差值之和的负值为边权。
(即为-(abs(x1-x2)+abs(y1-y2))),因为KM算法是求最大值,所以取负值,输出-ans就行

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespace std;const int maxn=1005;int g[maxn][maxn];bool visitx[maxn], visity[maxn];int lx[maxn], ly[maxn];int slack[maxn];int match[maxn];int n,m;char s[maxn][maxn];int nn,mm;struct jud{int x,y;}H[maxn],M[maxn];bool Hungary(int u) //匈牙利算法{    visitx[u] = true;    for(int i = 1; i <= n; ++i)    {        if(visity[i])            continue;        if(lx[u] + ly[i] == g[u][i])        {            visity[i] = true;            if(match[i] == -1 || Hungary(match[i]))            {                match[i] = u;                return true;            }        }        else //不在相等子图            slack[i] = min(slack[i], lx[u] + ly[i] - g[u][i]);    }    return false;}void KM(){    int temp;memset(match, -1, sizeof(match));    memset(lx, 0, sizeof(lx)); //初始化顶标    memset(ly, 0, sizeof(ly)); //ly[i]为0    for(int i = 1; i <= n; ++i) //lx[i]为权值最大的边        for(int j = 0; j <= m; ++j)            lx[i] = max(lx[i], g[i][j]);    for(int i = 1; i <= n; i++) //对n个点匹配    {        for(int j = 1; j <= n; j++)            slack[j] = INT_MAX;        while(1)        {            memset(visitx, false, sizeof(visitx));            memset(visity, false, sizeof(visity));            if(Hungary(i)) //匹配成功                break;            else //匹配失败,找最小值            {                temp = INT_MAX;                for(int j = 1; j <= n; j++)                    if(!visity[j])                        if(temp > slack[j])                            temp = slack[j];                for(int j = 1; j <= n; j++) //更新顶标                {                    if(visitx[j])                        lx[j] -= temp;                }                for(int j=1;j<=m;++j)                {                   if(visity[j])                        ly[j] += temp;                    else                        slack[j] -= temp;                }            }        }    }int ans = 0;    for(int i = 1; i <= m; i++) //权值相加        ans += g[match[i]][i];    printf("%d\n", -ans);}int main(){// freopen("in.txt","r",stdin);    while(scanf("%d %d", &nn,&mm) != EOF&&(nn||mm))    {n=m=1;for(int i=0;i<nn;i++){scanf("%s",s[i]);}for(int i=0;i<nn;i++){for(int j=0;j<mm;j++){if(s[i][j]=='H')H[n].x=i,H[n++].y=j;if(s[i][j]=='m')M[m].x=i,M[m++].y=j;}}n--;m--;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){g[i][j]=-(abs(H[i].x-M[j].x)+abs(H[i].y-M[j].y));}}KM();    }    return 0;}


0 0
原创粉丝点击