• 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 }

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

  • 相关阅读:
    移动终端app测试点总结
    Android测试环境搭建(win7)
    Jenkins知识地图
    Jenkins快速上手
    接口测试总结
    性能测试总结(三)--工具选型篇
    性能测试总结(二)---测试流程篇
    性能测试总结(一)---基础理论篇
    网友评论诺基亚和Android
    手撕伪鸡汤,人事部门经理给你的八个职场忠告
  • 原文地址:https://www.cnblogs.com/Griselda/p/2706534.html
Copyright © 2020-2023  润新知