hdu 1533 二分图的完备匹配(KM算法)

来源:互联网 发布:java书号书名 编辑:程序博客网 时间:2024/04/28 10:57

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

#include"iostream"
#include"algorithm"


#define min(a,b) (a)<(b)?(a):(b)
#define max(a,b) (a)>(b)?(a):(b)
#define max_int 0x7fffffff


using namespace std;




const int N = 200;
int mm[2][N];
int hh[2][N];
int mh[N][N];
int n,m;
int lx[N],ly[N];//标号
char visitx[N],visity[N];//用于深度搜索,同时可以标记S和T集合的点
int mat[N];//mat[y] = x;表示集合Y的y点的匹配为x
int slack[N];//slack[x]保存相对与顶点x的最小al,初始时为无穷大,dfs寻找增广路径的时候不断更新,并且会越来越小
int nx,ny;


typedef struct position
{
int x;
int y;
}NODE;




int find(int x)
{
int t,y;
visitx[x] = 1;
for(y = 1;y<=ny;y++)
{
if(!visity[y]&&mh[x][y]!=0)
{
t = lx[x]+ly[y]-mh[x][y];
if(t!=0)
{
slack[x] = min(slack[x],t);
}
else
{
visity[y] = 1;
if((mat[y]==-1||find(mat[y])))
{
mat[y] = x;
return 1;
}
}
}
}
return 0;
}




//寻找最优匹配
void find1()
{
int s;
int x,y;
int min_al;
for(s = 1;s<=nx;)
{
for(;;)
{
memset(visitx,0,sizeof(visitx));
memset(visity,0,sizeof(visity));
if(find(s))
{
s++;
break;
}
//在S集合中找到最小的lx[x]+ly[y]-weight[x][y],借助slack数组
min_al = max_int;
for(x = 1;x<=nx;x++)
{
if(visitx[x]&&slack[x]<min_al)
{
min_al = slack[x];
}
}
//更新S集合和T集合顶点标号
for(x = 1;x<=nx;x++)
{
if(visitx[x])
lx[x] -=min_al;
}
for(y = 1;y<=ny;y++)
{
if(visity[y])
ly[y] +=min_al;
}
}
}
}




//求得最大(小)权值
void sumy(int &sum)
{
int cost = 0;
int x,y;
for(x = 1;x<=nx;x++)
{
cost+=lx[x];
}
for(y = 1;y<=ny;y++)
{
cost+=ly[y];
}
sum = cost;
}




int main()
{
int i,j;
char c;
int k,l;
int sum;
while(scanf("%d%d",&n,&m)!=EOF)
{
k = 0;
l = 0;
if(n==0&&m==0)
break;
for(i = 0;i<n;i++)
{
for(j = 0;j<m;j++)
{
cin>>c;
if(c=='m')
{
mm[0][k] = i;
mm[1][k] = j;
k++;
}
if(c=='H')
{
hh[0][l] = i;
hh[1][l] = j;
l++;
}
}
}
memset(ly,0,sizeof(ly));
for(i = 0;i<=k;i++)
{
mat[i] = -1;
lx[i] = -20000;
slack[i] = max_int;
}
for(i = 0;i<k;i++)
{
for(j = 0;j<l;j++)
{
mh[i+1][j+1] = abs(mm[0][i]-hh[0][j])+abs(mm[1][i]-hh[1][j]);
mh[i+1][j+1] *=-1;
// lx[i+1] = max(lx[i+1],mh[i+1][j+1]);
}
}
nx = ny = k;

for(i = 1;i<=ny;i++)
{
for(j = 1;j<=ny;j++)
{
lx[i] = max(lx[i],mh[i][j]);
}
}
sum = 0;
find1();
sumy(sum);
printf("%d\n",-1*sum);
}
return 0;
}

原创粉丝点击