pku2195 Going Home(最大匹配模板)

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

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

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

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

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

先贴模板:

ContractedBlock.gif ExpandedBlockStart.gif 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

ContractedBlock.gif ExpandedBlockStart.gif 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/archive/2011/09/03/2165900.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值