zoukankan      html  css  js  c++  java
  • POJ-2195 Going Home---KM算法求最小权值匹配(存负边)

    题目链接:

    https://vjudge.net/problem/POJ-2195

    题目大意:

    给定一个N*M的地图,地图上有若干个man和house,且man与house的数量一致。man每移动一格需花费$1(即单位费用=单位距离),一间house只能入住一个man。现在要求所有的man都入住house,求最小费用。

    思路:

    KM算法传送门: 理解篇    运用篇

    每个man和house建立带权二分图,曼哈顿距离就是边的值,这里要求最小费用,也就是二分图最小权值匹配,但是KM算法求的是二分图最大权值匹配,所以此处用边的负数求最优匹配,求出来的答案的负数就是最小权匹配。

    注意:题目说house最多100,但是没有说明man的范围,所以man应该最多100*100。

    应该用house为二分图的X部,因为算法复杂度和X部点数有关,所以用点数少的house为X部

    因为存的是负数,在预处理X部的顶标值初始化应该是-INF,不能是0

    剩下的就是模板啦

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 const int maxx = 100 + 5;//house的上限
      7 const int maxy = 10000 + 5;//man的上限
      8 const int INF = 0x3f3f3f3f;
      9 int cntx, cnty;//X部的点的数目,Y部点的数目
     10 bool visx[maxx], visy[maxy];//是否加入增广路
     11 int wx[maxx], wy[maxy];//顶标值
     12 int cx[maxx], cy[maxy];//匹配的点
     13 int minz;//顶标值和边权最小的差值
     14 int Map[maxx][maxy];//保存边
     15 
     16 bool dfs(int u)
     17 {
     18     visx[u] = 1;
     19     for(int v = 1; v <= cnty; v++)
     20     {
     21         if(!visy[v])//还未加入增广路
     22         {
     23             int t = wx[u] + wy[v] - Map[u][v];
     24             //计算边权和顶标之差,为0表示是相等子图
     25             if(t == 0)
     26             {
     27                 visy[v] = 1;
     28                 if(cy[v] == -1 || dfs(cy[v]))//还未匹配或者反向找到增广路
     29                 {
     30                     cy[v] = u;
     31                     cx[u] = v;
     32                     //cout<<u<<"v"<<v<<endl;
     33                     return 1;
     34                 }
     35             }
     36             else if(t > 0)minz = min(minz, t);
     37         }
     38     }
     39     return 0;
     40 }
     41 
     42 int KM()
     43 {
     44     memset(cx, -1, sizeof(cx));
     45     memset(cy, -1, sizeof(cy));
     46     memset(wx, -INF, sizeof(wx));//注意,这里存的是负边,所以初始化必须是负无穷
     47     memset(wy, 0, sizeof(wy));
     48     for(int i = 1; i <= cntx; i++)//预处理出X部的顶标值
     49     {
     50         for(int j = 1; j <= cnty; j++)
     51         {
     52             wx[i] = max(wx[i], Map[i][j]);
     53             //cout<<wx[i]<<endl;
     54         }
     55     }
     56     for(int i = 1; i <= cntx; i++)
     57     {
     58         while(1)
     59         {
     60             minz = INF;
     61             memset(visx, 0, sizeof(visx));
     62             memset(visy, 0, sizeof(visy));
     63             if(dfs(i))break;
     64 
     65             for(int j = 1; j <= cntx; j++)
     66                 if(visx[j])wx[j] -= minz;
     67             for(int j = 1; j <= cnty; j++)
     68                 if(visy[j])wy[j] += minz;
     69         }
     70     }
     71     int ans = 0;
     72     for(int i = 1; i <= cntx; i++)
     73         if(cx[i] != -1)ans += Map[i][cx[i]];
     74     return ans;
     75 }
     76 struct node
     77 {
     78     int x, y;
     79     node(){}
     80     node(int x, int y):x(x), y(y){}
     81 };
     82 node house[maxx], man[maxy];
     83 char M[105][105];
     84 int main()
     85 {
     86     int n, m;
     87     while(cin >> n >> m && (n && m))
     88     {
     89         cntx = cnty = 0;
     90         for(int i = 0; i < n; i++)//读图
     91         {
     92             cin >> M[i];
     93             for(int j = 0; j < m; j++)
     94             {
     95                 if(M[i][j] == 'H')house[++cntx] = node(i, j);
     96                 else if(M[i][j] == 'm')man[++cnty] = node(i, j);
     97             }
     98         }
     99 
    100         for(int i = 1; i <= cntx; i++)//建图
    101         {
    102             for(int j = 1; j <= cnty; j++)
    103             {
    104                 Map[i][j] = -abs(house[i].x - man[j].x) - abs(house[i].y - man[j].y);
    105             }
    106         }
    107         cout<<(-KM())<<endl;
    108     }
    109     return 0;
    110 }
  • 相关阅读:
    shell编程基础干货
    HIVE的高级操作
    Linux service,挂载,定时任务等常用服务
    Linux(二)高级文本处理
    Linux基本使用命令
    07-MySQL 架构介绍
    06-Re: 视图&过程&触发器
    05-安装 MySQL5.7
    [04] 继承&聚合&war
    [03] 仓库&生命周期&插件目标
  • 原文地址:https://www.cnblogs.com/fzl194/p/8850226.html
Copyright © 2011-2022 走看看