poj 2195 KM算法(完备匹配)
2011-05-12 20:39
197 查看
题目链接:http://poj.org/problem?id=2195
题目大意:在n*m的矩阵中,有一些man和house,数目相等,要使每个man都回到一个house里,所走的距离为对应位置的行号差和列号差之和,求所需走的最小距离并输出
思路:很明显是二分图最小权值匹配问题,由于KM算法求的是最大权值匹配,故要将权值取负,然后用KM模板即可,最后结果再取反输出
对于KM算法,我还是处于懵懂状态,需要继续理解
貌似网上有用最小费用最大流解决的spfa方法,由于还没学,故有待继续学习
题目大意:在n*m的矩阵中,有一些man和house,数目相等,要使每个man都回到一个house里,所走的距离为对应位置的行号差和列号差之和,求所需走的最小距离并输出
思路:很明显是二分图最小权值匹配问题,由于KM算法求的是最大权值匹配,故要将权值取负,然后用KM模板即可,最后结果再取反输出
对于KM算法,我还是处于懵懂状态,需要继续理解
貌似网上有用最小费用最大流解决的spfa方法,由于还没学,故有待继续学习
#include<stdio.h> #include<math.h> #include<string.h> #define N 110 #define MAX 100000000 int visitx ,visity ,match ,w ,slack ,lx ,ly ; char map ; int hcount,mcount; struct node{ int r,c; }man ,home ; int dfs(int p) /*寻找完备匹配*/ { int i,t,temp; visitx[p]=1; for(i=1;i<=hcount;i++) { if(visity[i]) continue; temp=lx[p]+ly[i]-w[p][i]; if(temp==0) { visity[i]=1; t=match[i]; match[i]=p; if(t==0 || dfs(t)) return 1; match[i]=t; } else if(slack[i]>temp) slack[i]=temp; /*松弛,减小下面求d值时的时间复杂度*/ } return 0; } int KM() { int i,j,d,ans; memset(ly,0,sizeof(ly)); memset(match,0,sizeof(match)); for(i=1;i<=mcount;i++) { lx[i]=-MAX; /*注意此处初始化,是负值*/ for(j=1;j<=hcount;j++) if(lx[i]<w[i][j]) lx[i]=w[i][j]; } for(i=1;i<=mcount;i++) { for(j=1;j<=hcount;j++) slack[j]=MAX; while(1) { memset(visitx,0,sizeof(visitx)); memset(visity,0,sizeof(visity)); if(dfs(i))/*寻找完备匹配*/ break; d=MAX; for(j=1;j<=hcount;j++) if(!visity[j] && d>slack[j]) d=slack[j]; /*找出最小的d值来更新顶点标号*/ for(j=1;j<=mcount;j++) { if(visitx[j]) lx[j]-=d; if(visity[j]) ly[j]+=d; else slack[j]-=d; } } } ans=0; for(i=1;i<=mcount;i++) ans-=(lx[i]+ly[i]); /*结果加的权值需要再取反,才为结果*/ return ans; } int main() { int i,j,n,m; while(scanf("%d%d",&n,&m),n!=0||m!=0) { getchar(); /*此处要小心*/ hcount=mcount=0; for(i=0;i<n;i++) gets(map[i]); for(i=0;i<n;i++) for(j=0;j<m;j++) {/*不知为何此处记录的mcount和hcount从1开始存就正确,从0开始就错误,很纠结*/ if(map[i][j]=='m') { mcount++; man[mcount].r=i; man[mcount].c=j; } else if(map[i][j]=='H') { hcount++; home[hcount].r=i; home[hcount].c=j; } } for(i=1;i<=mcount;i++) /*KM算法求的是最大权的完美匹配,所以将权值取反,权值是距离*/ for(j=1;j<=hcount;j++) w[i][j]=-(abs(man[i].r-home[j].r)+abs(man[i].c-home[j].c)); printf("%d/n",KM()); } return 0; }
相关文章推荐
- 二分图完备匹配(最小费用 || KM) poj 2195 GoingHome
- 【POJ 2195】 Going Home(KM算法求最小权匹配)
- poj 2195 二分匹配KM算法
- POJ 2195 Going Home(最小权匹配、KM算法)
- 【POJ 2195】 Going Home(KM算法求最小权匹配)
- POJ-2195 Going Home (最小费用最大流初学 && 最大权二分匹配—KM算法)
- POJ 2195 Going Home【KM算法-二分图的最优匹配】
- KM算法 最优匹配(最大权匹配) hdu 2255 奔小康赚大钱 最小权匹配 poj 2195 Going Home
- POJ - 2195 Going Home (构图 最大匹配KM算法)
- 【POJ - 2195】Going Home(KM算法求二分图最小权匹配)
- poj 2195 二分图最优匹配 KM算法求最小值
- POJ 2195 Going Home (二分图最大权匹配、KM算法)
- POJ 2195 二分图最小权匹配KM算法
- poj 2195 Going Home(二分图最优匹配KM算法)
- poj 2195 Going Home 二分图最小权匹配KM算法
- POJ 2195 Going Home(KM算法——二分图最小权匹配)
- poj 2195 二分图最优匹配KM算法 模板题
- POJ-2195 Going Home 最小权值匹配
- 【原创】KM算法 ※HDU 2225 POJ 2195
- sicily 1013 poj 2195 km算法