poj 2195-Going Home解题报告

链接:http://poj.org/problem?id=2195

这道题是二分图的最佳匹配问题,而且属于最小匹配,km算法的模版题,题目保证了人数和房子数相等,这是自己第一道km算法题,刚开始对km算法不理解,看各种讲解,终于搞懂了其运行过程和能求出解的原因。km算法保证在整个算法的运行过程中对于匹配x,y保证lx[x]+ly[y]>=w(x,y);最终找到的是lx[x]+ly[y]=w(x,y)的解。

View Code
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #define N 200
  5 #define inf 0x7fffffff
  6 using namespace std;
  7 struct point
  8 {
  9     int x,y;
 10 };
 11 point ph[N],pm[N];
 12 int lx[N],ly[N];
 13 int map[N][N];
 14 int match[N];
 15 int usedx[N],usedy[N],flag;
 16 char g[N][N];
 17 int abs(int a)
 18 {
 19     return a>=0?a:-a;
 20 }
 21 int max(int a,int b)
 22 {
 23     return a>b?a:b;
 24 }
 25 int min(int a,int b)
 26 {
 27     return a<b?a:b;
 28 }
 29 int h,m;
 30 void build()
 31 {
 32     int i,j;
 33     for(i=1;i<=h;i++)
 34     for(j=1;j<=m;j++)
 35     map[i][j]=abs(ph[i].x-pm[j].x)+abs(ph[i].y-pm[j].y);
 36 }
 37 bool dfs(int x)
 38 {
 39     int i,j,k;
 40     usedx[x]=flag;
 41     for(i=1;i<=m;i++)
 42     {
 43         if(usedy[i]!=flag&&lx[x]+ly[i]==map[x][i])
 44         {
 45             usedy[i]=flag;
 46             if(match[i]==-1||dfs(match[i]))
 47             {
 48                 match[i]=x;
 49                 return true;
 50             }
 51         }
 52     }
 53     return false;
 54 }
 55 int km()
 56 {
 57     memset(lx,127,sizeof(lx));
 58     memset(ly,0,sizeof(ly));
 59     build();
 60     flag=0;
 61     int res=0;
 62     int i,j,k,d;
 63     for(i=1;i<=h;i++)
 64     for(j=1;j<=m;j++)
 65     lx[i]=min(lx[i],map[i][j]);//最大权匹配就取最大值,最小权匹配就取最小值
 66     memset(match,-1,sizeof(match));
 67     for(i=1;i<=h;i++)
 68     {
 69         flag++;
 70         while(!dfs(i))
 71         {
 72             d=inf;
 73             for(j=1;j<=h;j++)
 74             {
 75                 if(usedx[j]==flag)
 76                 for(k=1;k<=m;k++)
 77                 if(usedy[k]!=flag)
 78                 d=min(map[j][k]-lx[j]-ly[k],d);
 79             }
 80             for(j=1;j<=h;j++)
 81             if(usedx[j]==flag)
 82             lx[j]+=d;
 83             for(j=1;j<=m;j++)
 84             {
 85                 if(usedy[j]==flag)
 86                 ly[j]-=d;
 87             }
 88             flag++;
 89         }
 90     }
 91     for(i=1;i<=m;i++)
 92     res+=map[match[i]][i];
 93     return res;
 94 }
 95 int main()
 96 {
 97     int r,c,i,j,k;
 98     char s;
 99     while(scanf("%d%d",&r,&c)&&(r||c))
100     {
101         h=m=0;
102         for(i=1;i<=r;i++)
103         scanf("%s",g[i]+1);
104         for(i=1;i<=r;i++)//建图过程
105         for(j=1;j<=c;j++)
106         {
107             if(g[i][j]=='H')
108             {
109                 ph[++h].x=i;
110                 ph[h].y=j;
111             }
112             if(g[i][j]=='m')
113             {
114                 pm[++m].x=i;
115                 pm[m].y=j;
116             }
117         }
118         //printf("%d %d\n",h,m);
119         printf("%d\n",km());
120     }
121     return 0;
122 }

 

posted @ 2012-05-03 19:20  zhenhai  阅读(244)  评论(0编辑  收藏  举报