hdu1533 KM算法

来源:互联网 发布:西部数码域名转移管理 编辑:程序博客网 时间:2024/05/01 23:51

正解应该是最小费用流 但是这个情况太特殊了 正好可以用上km

⚠:填写代价矩阵的时候要取反 应为题目的意思是求最小,然后把结果再取反就是要求的答案了 


#include<stdio.h>#include<stdlib.h>#include<string.h>#include<iostream>#include<vector>#include<cstdio>using namespace std;vector<pair<int,int> >man,house;#define N 105#define INF 1 << 29int g[N][N], lx[N], ly[N], match[N];bool x[N], y[N];int slack[N];bool dfs(int u,int n){    x[u]=1;    for(int i=1;i<=n;i++)    {        int wt=lx[u]+ly[i]-g[u][i];        if(!y[i])        {            if(!wt)            {                y[i] = 1;                if(match[i] == -1 || dfs(match[i], n))                {                    match[i] = u;                    return 1;                }            }            else            {                if(slack[i]>wt) slack[i]=wt;            }        }    }    return 0;}int KM(int n){    memset(ly, 0, sizeof(ly));    memset(match, -1, sizeof(match));    for(int i = 1; i <= n; i++)    {        lx[i] = -INF;        for(int j = 1; j <= n; j++)        {            if(lx[i]<g[i][j])                lx[i]=g[i][j];        }    }    for(int k = 1; k <= n; k++)    {        memset(x, 0, sizeof(x));        memset(y, 0, sizeof(y));        for(int j=0;j<=n+1;j++)            slack[j]=0x7fffffff;        while(!dfs(k, n))        {            int min = INF;            for(int i=1;i<=n;i++)                if(!y[i]&&min>slack[i])                    min=slack[i];            for(int i = 1; i <= n; i++)            {                if(x[i]) lx[i] -= min, x[i] = 0;                if(y[i]) {ly[i] += min, y[i] = 0;}                else slack[i]-=min;            }        }    }    int sum = 0;    for(int i = 1; i <= n; i++)        sum += g[match[i]][i];    return sum;}int main(){    int n,m,num;    char ss[1005];    while(~scanf("%d%d",&n,&m))    {        if(n==0&&m==0)break;        man.clear();        house.clear();        num=0;        for(int i=0;i<n;++i)        {            scanf("%s",ss);            for(int j=0;j<m;++j)            {                if(ss[j]=='m'){man.push_back(make_pair(i,j));num++;}                else if(ss[j]=='H'){house.push_back(make_pair(i,j));}            }        }        for(int i=0;i<num;++i)        {            for(int j=0;j<num;++j)            {                g[i+1][j+1]=abs(man[i].first-house[j].first)+abs(man[i].second-house[j].second);                g[i+1][j+1]=-g[i+1][j+1];            }        }        int ans=KM(num);        printf("%d\n",-ans);    }}


0 0