码迷,mamicode.com
首页 > 其他好文 > 详细

poj 2195 二分图带权匹配

时间:2015-03-05 00:05:09      阅读:227      评论:0      收藏:0      [点我收藏+]

标签:

题意:有一个矩阵,某些格有人,某些格有房子,每个人可以上下左右移动,问给每个人进一个房子,所有人需要走的距离之和最小是多少。

貌似以前见过很多这样类似的题,都不会,现在知道是用KM算法做了

KM算法目前还没弄懂,先套模板做

 

Sample Input

2 2
.m
H.
5 5
HH..m
.....
.....
.....
mm..H
7 8
...H....
...H....
...H....
mmmHmmmm
...H....
...H....
...H....
0 0

Sample Output

2
10
28


  1 #include<stdio.h>
  2 #include<iostream>
  3 #include<string.h>
  4 #include<algorithm>
  5 #include<math.h>
  6 using namespace std;
  7 const int MAXN=120;
  8 const int INF=0x3fffffff;
  9 int g[MAXN][MAXN],match1[MAXN],match2[MAXN];
 10 int KM(int m,int n)
 11 {
 12     int i,j,k,p,q;
 13     int l1[MAXN],l2[MAXN];
 14     int s[MAXN],t[MAXN];
 15     int ret=0;
 16     for(i=0;i<m;i++)
 17     {
 18         l1[i]=-INF;
 19         for(j=0;j<n;j++)
 20           if(g[i][j]>l1[i])
 21              l1[i]=g[i][j];
 22         if(l1[i]==-INF) return -1;//无法匹配
 23     }
 24     for(i=0;i<n;i++)l2[i]=0;
 25 
 26     memset(match1,-1,sizeof(match1));
 27     memset(match2,-1,sizeof(match2));
 28     for(i=0;i<m;i++)
 29     {
 30         memset(t,-1,sizeof(t));
 31         for(s[p=q=0]=i;p<=q&&match1[i]<0;p++)
 32             for(k=s[p],j=0;j<n&&match1[i]<0;j++)
 33                 if(l1[k]+l2[j]==g[k][j]&&t[j]<0)
 34                 {
 35                     s[++q]=match2[j],t[j]=k;
 36                     if(s[q]<0)
 37                       for(p=j;p>=0;j=p)
 38                          match2[j]=k=t[j],p=match1[k],match1[k]=j;
 39                 }
 40 
 41         if(match1[i]<0)
 42         {
 43             for(i--,p=INF,k=0;k<=q;k++)
 44                for(j=0;j<n;j++)
 45                  if(t[j]<0&&l1[s[k]]+l2[j]-g[s[k]][j]<p)
 46                      p=l1[s[k]]+l2[j]-g[s[k]][j];
 47 
 48 
 49             for(j=0;j<n;j++)if(t[j]>=0)l2[j]+=p;
 50             for(k=0;k<=q;k++)l1[s[k]]-=p;
 51         }
 52     }
 53     for(i=0;i<m;i++)
 54     {
 55         if(match1[i]<0)return -1;//无法匹配
 56         if(g[i][match1[i]]<=-INF)return -1;
 57         ret+=g[i][match1[i]];
 58     }
 59     return ret;
 60 }
 61 struct Node
 62 {
 63     int x,y;
 64 };
 65 Node node1[MAXN],node2[MAXN];
 66 char str[MAXN];
 67 int main()
 68 {
 69     int n,m;
 70     int nx,ny;
 71     while(scanf("%d%d",&n,&m)!=EOF)
 72     {
 73         if(n==0&&m==0)break;
 74         nx=0;
 75         ny=0;
 76         for(int i=0;i<n;i++)
 77         {
 78             scanf("%s",&str);
 79             for(int j=0;j<m;j++)
 80             {
 81                 if(str[j]==m)
 82                 {
 83                     node1[nx].x=i;
 84                     node1[nx].y=j;
 85                     nx++;
 86                 }
 87                 else if(str[j]==H)
 88                 {
 89                     node2[ny].x=i;
 90                     node2[ny].y=j;
 91                     ny++;
 92                 }
 93             }
 94         }
 95         for(int i=0;i<nx;i++)
 96         for(int j=0;j<ny;j++)
 97         {
 98             g[i][j]=-abs(node1[i].x-node2[j].x)-abs(node1[i].y-node2[j].y);
 99         }
100         printf("%d\n",-KM(nx,ny));
101     }
102     return 0;
103 }

 

poj 2195 二分图带权匹配

标签:

原文地址:http://www.cnblogs.com/cnblogs321114287/p/4314645.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!