pku2195 Going Home(最大匹配模板)

模板题来的,构完图之后就是直接的模板了,可惜对于这个算法还是了解的不够深…………

若求得的是最大匹配,则将权值为正,若为最小匹配,则将权值该为相反数

此模板默认所有数组默认下标从1 开始,复杂度O(n^3)
mat 表示邻接矩阵,nx,ny表示二分的大小

lx,ly表示为顶标,fx[i],fy[i]标记十分访问过该点

mx[i],my[i] 表示匹配

先贴模板:

KM算法模板
#include <iostream>

using namespace std;

const int MAXN = 110;
const int INF = 0x7FFFFFFF;

int nx, ny, w[MAXN][MAXN], lx[MAXN], ly[MAXN];
int fx[MAXN], fy[MAXN], matx[MAXN], maty[MAXN];

int 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 perfect_match()
{
int ret = 0;
memset(ly,
0, sizeof(ly));
for (int i = 1; i <= nx; i++)
{
lx[i]
= -INF;
for (int 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 (int i = 1; i <= nx; i++)
{
memset(fx,
-1, sizeof(fx));
memset(fy,
-1, sizeof(fy));
if (!path(i))
{
i
--;
int p = INF;
for (int k = 1; k <= nx; k++) if (fx[k] > 0)
for (int 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 (int j = 1; j <= ny; j++) ly[j] += fy[j]<0 ? 0 : p;
for (int j = 1; j <= nx; j++) lx[j] -= fx[j]<0 ? 0 : p;
}
}
//for (int i = 1; i <= ny; i++) ret += w[maty[i]][i];
for (int i = 1; i <= ny; i++)
if (maty[i]!=-1) ret += w[maty[i]][i];

return ret;
}

pku 2195

View Code
#include<iostream>
#define inf 100000000
using namespace std;
int mx[110],my[110],mat[110][110],n,fx[110],fy[110],lx[110],ly[110];
struct house
{
int x,y;
}h[
110];
struct people
{
int x,y;
}p[
110];
inline
int dis(int i,int j)
{
return abs(h[j].x-p[i].x)+abs(h[j].y-p[i].y);
}
int path(int u)
{
fx[u]
= 1;
for (int v = 1; v <= n; v++) if (lx[u] + ly[v] == mat[u][v] && fy[v] < 0)
{
fy[v]
= 1;
if (my[v] < 0 || path(my[v]))
{
mx[u]
= v;
my[v]
= u;
return 1;
}
}
return 0;
}

int perfect_match()
{
int ret = 0;
memset(ly,
0, sizeof(ly));
for (int i = 1; i <= n; i++)
{
lx[i]
= -inf;
for (int j = 1; j <= n; j++) if (mat[i][j] > lx[i]) lx[i] = mat[i][j];
}
memset(mx,
-1, sizeof(mx));
memset(my,
-1, sizeof(my));
for (int i = 1; i <= n; i++)
{
memset(fx,
-1, sizeof(fx));
memset(fy,
-1, sizeof(fy));
if (!path(i))
{
i
--;
int p = inf;
for (int k = 1; k <= n; k++) if (fx[k] > 0)
for (int j = 1; j <= n; j++) if (fy[j] < 0 && lx[k] + ly[j] - mat[k][j] < p)
p
=lx[k]+ly[j]-mat[k][j];
for (int j = 1; j <= n; j++) ly[j] += fy[j]<0 ? 0 : p;
for (int j = 1; j <= n; j++) lx[j] -= fx[j]<0 ? 0 : p;
}
}
for (int i = 1; i <= n; i++)
ret
+= mat[my[i]][i];

return ret;
}

int main()
{
int n1,m1;
char a;
while(scanf("%d %d",&n1,&m1)==2&&(n1||m1))
{
int count1=0,count2=0;
for(int i=1;i<=n1;i++)
{
getchar();
for(int j=1;j<=m1;j++)
{
scanf(
"%c",&a);
if(a=='H') h[++count1].x=i,h[count1].y=j;
if(a=='m') p[++count2].x=i,p[count2].y=j;
}
}
for(int i=0;i<110;i++)
for(int j=0;j<110;j++)
mat[i][j]
=-inf;
for(int i=1;i<=count2;i++)
for(int j=1;j<=count1;j++)
mat[i][j]
=-dis(i,j);
n
=count1;
printf(
"%d\n",-perfect_match());
}
return 0;
}
原文地址:https://www.cnblogs.com/nanke/p/2165900.html