• uva 11383 Golden Tiger Claw


    题意:

    给出一个n * n的矩阵,要求给每一行和每一列安排一个数字,使得对于每个数字a[i][j],这一行安排的数字row[i]和这一列安排的数字col[j]满足row[i] + col[j] >= a[i][j]。要求使得每一行安排的数字和每一列安排的数字之和最小。输出每一行和每一列安排的数字,再输出最小值。

    思路:

    对于row[i] + col[j] >= a[i][j]这个条件,可以联想到KM算法中的一个式子lx[i] + ly[j] >= w[i][j],于是就可以把每一行安排的值视为左顶标,每一列安排的值视为右顶标,然后进行一次KM算法求最大匹配,那么得到的左右顶标之和就是最小的,即每一行安排的数字和每一列安排的数字之和最小。

    有两个地方比较难想:

    第一是求的是最小值,但是求的却是最大匹配,不是最小匹配,因为我们求的最后结果是满足lx[i] + ly[j] >= w[i][j]的,但是最小匹配满足的条件是lx[i] + ly[j] >= -w[i][j],这不满足条件。

    第二是如何证明求出来的是最小值,因为求出的匹配是一个导出子图,而导出子图的每一条边都满足lx[i] + ly[j] == w[i][j],如果把这个结果减小,那么必然存在某些边有lx[i] + ly[j] < w[i][j],这样就不满足题中所给条件。

    复杂度O(n^3)。

    代码:

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <algorithm>
      4 using namespace std;
      5 
      6 const int N = 505;
      7 const int inf = 0x3f3f3f3f;
      8 
      9 int lx[N],ly[N];
     10 bool vis_x[N],vis_y[N];
     11 int slack[N];
     12 int match[N];
     13 int w[N][N];
     14 
     15 bool dfs(int u,int n)
     16 {
     17     vis_x[u] = 1;
     18     
     19     for (int i = 0;i < n;i++)
     20     {
     21         if (vis_y[i]) continue;
     22         
     23         int gap = lx[u] + ly[i] - w[u][i];
     24         
     25         if (gap == 0)
     26         {
     27             vis_y[i] = 1;
     28             
     29             if (match[i] == -1 || dfs(match[i],n))
     30             {
     31                 match[i] = u;
     32                 return true;
     33             }
     34         }
     35         else
     36         {
     37             slack[i] = min(slack[i],gap);
     38         }
     39     }
     40     
     41     return false;
     42 }
     43 
     44 int km(int n)
     45 {
     46     memset(match,-1,sizeof(match));
     47     memset(ly,0,sizeof(ly));
     48     //for (int i = 0;i < n;i++) lx[i] = -inf;
     49     
     50     for (int i = 0;i < n;i++)
     51     {
     52         lx[i] = w[i][0];
     53         
     54         for (int j = 1;j < n;j++)
     55         {
     56             lx[i] = max(lx[i],w[i][j]);
     57         }
     58     }
     59     
     60     for (int i = 0;i < n;i++)
     61     {
     62         memset(slack,inf,sizeof(slack));
     63         
     64         while (1)
     65         {
     66             memset(vis_x,0,sizeof(vis_x));
     67             memset(vis_y,0,sizeof(vis_y));
     68             
     69             if (dfs(i,n)) break;
     70             
     71             int d = inf;
     72             
     73             for (int j = 0;j < n;j++)
     74             {
     75                 d = min(d,slack[j]);
     76             }
     77             
     78             for (int j = 0;j < n;j++)
     79             {
     80                 if (vis_x[j]) lx[j] -= d;
     81                 
     82                 if (vis_y[j]) ly[j] += d;
     83                 //else slack[j] -= d;
     84             }
     85         }
     86     }
     87     
     88     int ans = 0;
     89     
     90     for (int i = 0;i < n;i++)
     91     {
     92         ans += w[match[i]][i];
     93     }
     94     
     95     return ans;
     96 }
     97 
     98 int main()
     99 {
    100     int n;
    101     
    102     while (scanf("%d",&n) != EOF)
    103     {
    104         for (int i = 0;i < n;i++)
    105         {
    106             for (int j = 0;j < n;j++)
    107             {
    108                 int t;
    109                 
    110                 scanf("%d",&t);
    111                 
    112                 w[i][j] = t;
    113             }
    114         }
    115         
    116         
    117         
    118         int res = km(n);
    119         int ans = 0;
    120         
    121         for (int i = 0;i < n;i++)
    122         {
    123             ans += (lx[i]);
    124             printf("%d%c",lx[i],i == n - 1 ? '
    ' : ' ');
    125         }
    126         
    127         for (int i = 0;i < n;i++)
    128         {
    129             ans += (ly[i]);
    130             printf("%d%c",ly[i],i == n - 1 ? '
    ' : ' ');
    131         }
    132         
    133         printf("%d
    ",res);
    134     }
    135     
    136     return 0;
    137 }
  • 相关阅读:
    VUE DEVTOOLS 安装方法(npm cnpm 安装失败找不到安装工具问题解决方法)
    idea 注释模版
    阿里巴巴编码规范
    JRebel 实现热部署
    SPRING 扩展组件
    oracle 闪回
    ORACLE 日常
    springboot log4j
    支付宝异步回调验证签名的那些走过的坑
    ASP.NET MVC5(一)—— URL路由
  • 原文地址:https://www.cnblogs.com/kickit/p/8809109.html
Copyright © 2020-2023  润新知