题意:

  给一个n*n的矩阵,每个格子中有正整数w[i][j],试为每行和每列分别确定一个数字row[i]和col[i],使得任意格子w[i][j]<=row[i]+col[j]恒成立。先输row,再输出col,再输出全部总和(总和应尽量小)。

思路:

  本题与匹配无关,但可以用KM算法解决。

  KM算法中的顶标就是保持了Lx[i]+ly[j]>=g[i][j]再求最大权和匹配的,但这个最大权和并没有关系。我们可以将row[i]看成一个男的,col[i]看成一个女的,这样男女的总数就相等。

  一般来说,Lx[i]或Ly[i]仅需要取该行/列中最大的那个数即可保证满足要求,但是这样太大了,可以通过调整来使得总和更小。而KM算法的过程就是一个调整的过程,每一对匹配的男女的那条边的权值就会满足等号 w[i][j]=row[i]+col[j],至少需要一个来满足等号,这样才能保证row[i]+col[j]是达到最小的,即从j列看,col[j]满足条件且最小,从i行看,row[i]满足条件且最小。这刚好与KM算法求最大权和一样。

  1. #include <bits/stdc++.h>
  2. #define LL long LONG_LONG_MAX
  3. #define INF 0x7f7f7f7f
  4. #define LL long long
  5. using namespace std;
  6. const int N=;
  7.  
  8. int grid[N][N], girl[N];
  9. int Lx[N], Ly[N], slack[N];
  10. bool S[N], T[N];
  11. int n;
  12.  
  13. bool DFS(int x)
  14. {
  15. S[x]=true;
  16. for(int i=; i<=n; i++)
  17. {
  18. if(T[i]) continue;
  19. int tmp=Lx[x]+Ly[i]-grid[x][i];
  20. if(tmp==)
  21. {
  22. T[i]=true;
  23. if(girl[i]== || DFS(girl[i]))
  24. {
  25. girl[i]=x;
  26. return true;
  27. }
  28. }
  29. else if(tmp<slack[i])
  30. slack[i]=tmp;
  31. }
  32. return false;
  33. }
  34.  
  35. int KM()
  36. {
  37. memset(girl, , sizeof(girl));
  38. memset(Lx, , sizeof(Lx));
  39. memset(Ly, , sizeof(Ly));
  40. for(int i=; i<=n; i++)
  41. for(int j=; j<=n; j++)
  42. Lx[i]=max(Lx[i], grid[i][j]);
  43.  
  44. for(int i=; i<=n; i++) //对于每个树
  45. {
  46. for(int j=; j<=n; j++) slack[j]=INF;
  47. while()
  48. {
  49. memset(S, , sizeof(S));
  50. memset(T, , sizeof(T));
  51. if( DFS(i) ) break; //找到匹配的蚂蚁
  52.  
  53. int d=INF;
  54. for(int j=; j<=n; j++) //找最小D
  55. {
  56. if(!T[j] && d>slack[j])
  57. d=slack[j];
  58. }
  59.  
  60. for(int j=; j<=n; j++) //更新树
  61. {
  62. if(S[j])
  63. Lx[j]-=d;
  64. }
  65.  
  66. for(int j=; j<=n; j++) //更新蚂蚁
  67. {
  68. if(T[j]) Ly[j]+=d;
  69. else slack[j]-=d;
  70. }
  71. }
  72. }
  73. int sum=;
  74. for(int i=; i<=n; i++) sum+=Lx[i]+Ly[i];
  75. return sum;
  76. }
  77.  
  78. int main()
  79. {
  80. freopen("input.txt", "r", stdin);
  81. while(~scanf("%d",&n))
  82. {
  83. memset(grid, , sizeof(grid));
  84. for(int i=; i<=n; i++)
  85. for(int j=; j<=n; j++)
  86. scanf("%d",&grid[i][j]);
  87.  
  88. int ans=KM();
  89. printf("%d", Lx[]);//值得注意的输出格式。
  90. for(int i=; i<=n; i++) printf(" %d", Lx[i]);
  91. printf("\n");
  92. printf("%d",Ly[]);
  93. for(int i=; i<=n; i++) printf(" %d", Ly[i]);
  94. printf("\n");
  95. printf("%d\n", ans);
  96. }
  97. return ;
  98. }

AC代码

UVA 11383 Golden Tiger Claw 金虎爪(KM算法)的更多相关文章

  1. UVA 11383 - Golden Tiger Claw(二分图完美匹配扩展)

    UVA 11383 - Golden Tiger Claw 题目链接 题意:给定每列和每行的和,给定一个矩阵,要求每一个格子(x, y)的值小于row(i) + col(j),求一种方案,而且全部行列 ...

  2. uva11383 Golden Tiger Claw 深入理解km算法

    /** 题目: uva11383 Golden Tiger Claw 深入理解km算法 链接:https://vjudge.net/problem/UVA-11383 题意:lv 思路:lrj训练指南 ...

  3. 【KM算法】UVA 11383 Golden Tiger Claw

    题目大意 给你一个\(n×n\)的矩阵G,每个位置有一个权,求两个一维数组\(row\)和\(col\),使\(row[i] + col[j]\ge G[i][j]\),并且\(∑row+∑col\) ...

  4. UVA 11383 Golden Tiger Claw 题解

    题目 --> 题解 其实就是一个KM的板子 KM算法在进行中, 需要满足两个点的顶标值之和大于等于两点之间的边权, 所以进行一次KM即可. KM之后, 顶标之和就是最小的.因为如果不是最小的,就 ...

  5. Uva - 11383 - Golden Tiger Claw

    题意:一个N*N的矩阵,第i行第j列的元素大小为w[i][j],每行求一个数row[i],每列求一个数col[j],使得row[i] + col[j] >= w[i][j],且所有的row[]与 ...

  6. UVA 11383 Golden Tiger Claw(最佳二分图完美匹配)

    题意:在一个N*N的方格中,各有一个整数w(i,j),现在要求给每行构造row(i),给每列构造col(j),使得任意w(i,j)<=row(i)+col(j),输出row(i)与col(j)之 ...

  7. 【UVA11383】 Golden Tiger Claw 【二分图KM算法(板子)】

    题目 题目传送门:https://www.luogu.com.cn/problem/UVA11383 分析 最近刚刚学了二分图,然后来了一个这样的题,看完题意之后,稍微想一想就能想出来是一个二分图,然 ...

  8. 【UVA 11383】 Golden Tiger Claw (KM算法副产物)

    Omi, Raymondo, Clay and Kimiko are on new adventure- in search of new Shen Gong Wu. But EvilBoy Geni ...

  9. UVA11383 Golden Tiger Claw

    题目 UVA11383 Golden Tiger Claw 做法 \(KM\)好题啊,满足所有边\(l(x)+l(y)≥w(x,y)\)(个人理解,如不对请及时留言),这样能满足\(\sum\limi ...

随机推荐

  1. [STL]双层级配置器

    考虑到过多“小型区块”可能造成的内存碎片问题,SGI设计了双层级配置器: 第一级配置器直接调用malloc()和free(): 第二级配置器分两种情况:当配置区块大于128字节时,调用第一级配置器:当 ...

  2. [读]剑指offer

    研二的开始找工作了,首先祝愿他们都能够找到自己满意的工作.看着他们的身影,自问明年自己这个时候是否可以从容面对呢?心虚不已,赶紧从老严那儿讨来一本<剑指offer>.在此顺便将自己做题所想 ...

  3. PCA和LDA

    一.PCA     在讲PCA之前,首先有人要问了,为什么我们要使用PCA,PCA到底是干什么的?这里先做一个小小的解释,举个例子:在人脸识别工作中一张人脸图像是60*60=3600维,要处理这样的数 ...

  4. CodeIgniter API

    http://apigen.juzna.cz/doc/EllisLab/CodeIgniter/tree.html Classes CI_Benchmark CI_Calendar CI_Cart C ...

  5. URAL 1152. False Mirrors (记忆化搜索 状压DP)

    题目链接 题意 : 每一颗子弹破坏了三个邻近的阳台.(第N个阳台是与第1个相邻)射击后后的生存的怪物都对主角造成伤害- 如此,直到所有的怪物被消灭,求怎样射击才能受到最少伤害. 思路 : 状压,数据不 ...

  6. light oj 1393 - Crazy Calendar 博弈论

    思路:当移到右下角时,就不能移动了.所以与右下角的奇偶性相同的位置,都不能直接到达,先手必败! 只需考虑与右下角奇偶不同的位置,可以看成NIM博弈.最后NIM和不为0的胜,否者败!! 代码如下: #i ...

  7. light oj 1068 - Investigation 数位DP

    思路:典型的数位DP!!! dp[i][j][k]:第i位,对mod取余为j,数字和对mod取余为k. 注意:由于32位数字和小于95,所以当k>=95时,结果肯定为0. 这样数组就可以开小点, ...

  8. Combination Sum III

    https://leetcode.com/problems/combination-sum-iii/ Find all possible combinations of k numbers that ...

  9. 【poj3208-Apocalypse Someday】数位DP

    题意:问你在所有包含666的数中,第n大的是多少.(1 ≤ n ≤ 50,000,000) .开头几个是666, 1666, 2666, 3666, 4666, 5666… 题解: 这题可以用AC自动 ...

  10. lintcode:字符串置换

    题目 给定两个字符串,请设计一个方法来判定其中一个字符串是否为另一个字符串的置换. 置换的意思是,通过改变顺序可以使得两个字符串相等. 样例 "abc" 为 "cba&q ...