poj2195——Going Home

本文介绍了一种基于Kuhn-Munkres算法实现的最小权值匹配方法,详细展示了算法的具体步骤,并通过实例代码进行了解释说明。该算法适用于解决一些特定的匹配问题,如在加权二分图中寻找最小权值完美匹配。

最小权值匹配,跟最大权值匹配差不多,但有些地方需改变:

1:t=gg[u][v]-lx[u]-ly[v];

2:for(i=0;i<topx;i++) { min=1000; for(j=0;j<topy;j++) if(gg[i][j]<min)min=gg[i][j]; lx[i]=min; }

3:for(j=0;j<topx;j++) if(vx[j]) lx[j]+=d; for(j=0;j<topy;j++) if(vy[j]) ly[j]-=d;

其他地方基本是最大匹配的模板。当然,这题还可以用MAX-其权值,反过来求最大匹配!

#include<stdio.h> #include<string.h> char g[102][102]; #define max 5002 struct node { int x,y; }cx[max],cy[max]; int gg[max][max]; int n,m,topx,topy; int fbs(int a){ if(a>=0) return a;else return -a;} int lx[max],ly[max],my[max],slack[max]; bool vx[max],vy[max]; bool dfs(int u) { int v,t; vx[u]=1; for(v=0;v<topy;v++) { if(!vy[v]) { t=gg[u][v]-lx[u]-ly[v]; if(t==0) { vy[v]=1; if(my[v]==-1||dfs(my[v])) { my[v]=u;return true; } } else slack[v]=slack[v]<t?slack[v]:t; } } return false; } void KM() { int i,j,min,d; for(i=0;i<topx;i++) { min=1000; for(j=0;j<topy;j++) if(gg[i][j]<min)min=gg[i][j]; lx[i]=min; } memset(ly,0,sizeof(ly)); memset(my,-1,sizeof(my)); for(i=0;i<topx;i++) { memset(slack,127,sizeof(slack)); while(1) { memset(vx,0,sizeof(vx)); memset(vy,0,sizeof(vy)); if(dfs(i)) break; d=max; for(j=0;j<topy;j++) if(!vy[j]) d=d<slack[j]?d:slack[j]; for(j=0;j<topx;j++) if(vx[j]) lx[j]+=d; for(j=0;j<topy;j++) if(vy[j]) ly[j]-=d; } } int ans=0; for(i=0;i<topy;i++) { if(my[i]!=-1) ans+=gg[my[i]][i]; } printf("%d\n",ans); } int main() { int i,j; while(scanf("%d%d",&n,&m)!=EOF) { topx=0;topy=0; if(n==0&&m==0) break; for(i=1;i<=n;i++) scanf("%s",&g[i]); for(i=1;i<=n;i++) for(j=0;j<m;j++) { if(g[i][j]=='H'){ cy[topy].x=i;cy[topy].y=j+1; topy++; } else if(g[i][j]=='m'){ cx[topx].x=i;cx[topx].y=j+1; topx++; } } for(i=0;i<topx;i++) { for(j=0;j<topy;j++){ gg[i][j]=fbs(cx[i].x-cy[j].x)+fbs(cx[i].y-cy[j].y); } } KM(); } }

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值