POJ 2195 【二分图最佳匹配】.cpp
题意:
有 n 个房子和 n 个人
每个人走一个单元你就要付 1$
有什么办法可以让把所有人都分派到房子里 而花费最少
输入:
给出n m 表示该矩阵由n 行 m 列组成
然后给出一个n*m的图
. 表示空地 H 表示房子 m 表示人
思路:
二分图最佳匹配<有权还要完全匹配>
Tips:
建图很有趣~
Code:
View Code
1 #include <stdio.h> 2 #include <cstring> 3 #include <cmath> 4 #define M 110 5 #define inf 0x1f1f1f1f 6 7 struct Node 8 { 9 int x; 10 int y; 11 }man[110], home[110]; 12 13 int n,nx,ny; 14 int link[M],lx[M],ly[M],slack[M]; //lx,ly为顶标,nx,nx分别为x点集y点集的个数 15 int visx[M],visy[M],w[M][M]; 16 17 int DFS(int x) 18 { 19 visx[x] = 1; 20 for (int y = 1;y <= nx;y ++) 21 { 22 if (visy[y]) 23 continue; 24 int t = lx[x] + ly[y] - w[x][y]; 25 if (t == 0) // 26 { 27 visy[y] = 1; 28 if (link[y] == -1||DFS(link[y])) 29 { 30 link[y] = x; 31 return 1; 32 } 33 } 34 else if (slack[y] > t) //不在相等子图中slack 取最小的 35 slack[y] = t; 36 } 37 return 0; 38 } 39 int KM() 40 { 41 int i,j; 42 memset (link,-1,sizeof(link)); 43 memset (ly,0,sizeof(ly)); 44 for (i = 1;i <= nx;i ++) //lx初始化为与它关联边中最大的 45 for (j = 1,lx[i] = -inf;j <= nx;j ++) 46 if (w[i][j] > lx[i]) 47 lx[i] = w[i][j]; 48 49 for (int x = 1;x <= nx;x ++) 50 { 51 for (i = 1;i <= nx;i ++) 52 slack[i] = inf; 53 while (1) 54 { 55 memset (visx,0,sizeof(visx)); 56 memset (visy,0,sizeof(visy)); 57 if (DFS(x)) //若成功(找到了增广轨),则该点增广完成,进入下一个点的增广 58 break; //若失败(没有找到增广轨),则需要改变一些点的标号,使得图中可行边的数量增加。 59 //方法为:将所有在增广轨中(就是在增广过程中遍历到)的X方点的标号全部减去一个常数d, 60 //所有在增广轨中的Y方点的标号全部加上一个常数d 61 int d = inf; 62 for (i = 1;i <= nx;i ++) 63 if (!visy[i]&&d > slack[i]) 64 d = slack[i]; 65 for (i = 1;i <= nx;i ++) 66 if (visx[i]) 67 lx[i] -= d; 68 for (i = 1;i <= nx;i ++) //修改顶标后,要把所有不在交错树中的Y顶点的slack值都减去d 69 if (visy[i]) 70 ly[i] += d; 71 else 72 slack[i] -= d; 73 } 74 } 75 int res = 0; 76 for (i = 1;i <= nx;i ++) 77 if (link[i] > -1) 78 res += w[link[i]][i]; 79 return -res; 80 } 81 82 int main () 83 { 84 int i, j, k; 85 int m; 86 char G[110][110]; 87 while (scanf("%d %d", &n, &m)!=EOF) 88 { 89 if(n == 0 && m == 0) break; 90 nx = 1, ny = 1; 91 // memset (w,0,sizeof(w)); 92 getchar(); 93 for(i = 0; i < n; ++i) 94 gets(G[i]); 95 96 for(i = 0; i < n; ++i) 97 for(j = 0; j < m; ++j) { 98 if(G[i][j] == 'm') { 99 man[nx].x = i; 100 man[nx++].y = j; 101 } 102 else if(G[i][j] == 'H') { 103 home[ny].x = i; 104 home[ny++].y = j; 105 } 106 } 107 108 for(i = 1; i < nx; ++i) 109 for(j = 1; j < ny; ++j) { 110 w[i][j] = -fabs(man[i].x - home[j].x) - fabs(man[i].y - home[j].y); 111 } 112 113 nx--; 114 int ans = KM(); 115 printf ("%d\n",ans); 116 } 117 return 0; 118 }