[关闭]
@Metralix 2018-03-08T14:45:38.000000Z 字数 1470 阅读 799

DIV1(6)二分图匹配


B - Golden Tiger Claw

二分图匹配


题目大意

500*500带权格子,每行每列要确定一个值,使row[i]+col[j] >= val[i][j],要使所有row值和col值的和最小
  输出每行的row[i],和每列的col[i]

解题思路

利用二分图最佳完美匹配当中的l(x)+l(y)>=w(i,j),直接用KM算法即可。
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <algorithm>
  4. #include <iostream>
  5. using namespace std;
  6. const int maxn=510;
  7. const int inf=0x3f3f3f3f;
  8. int n,nx,ny;
  9. int link[maxn],lx[maxn],ly[maxn],slack[maxn];
  10. int visx[maxn],visy[maxn],w[maxn][maxn];
  11. int DFS(int x)
  12. {
  13. visx[x]=1;
  14. for(int y=1;y<=ny;y++)
  15. {
  16. if(visy[y])continue;
  17. int t=lx[x]+ly[y]-w[x][y];
  18. if(t==0)
  19. {
  20. visy[y]=1;
  21. if(link[y]==-1||DFS(link[y]))
  22. {
  23. link[y]=x;
  24. return 1;
  25. }
  26. }
  27. else if(slack[y]>t)
  28. {
  29. slack[y]=t;
  30. }
  31. }
  32. return 0;
  33. }
  34. int KM()
  35. {
  36. memset(link,-1,sizeof(link));
  37. memset(ly,0,sizeof(ly));
  38. for(int i=1;i<=nx;i++)
  39. {
  40. lx[i]=-inf;
  41. for(int j=1;j<=ny;j++)
  42. {
  43. if(w[i][j]>lx[i])
  44. lx[i]=w[i][j];
  45. }
  46. }
  47. for(int x=1;x<=nx;x++)
  48. {
  49. for(int i=1;i<=ny;i++)
  50. slack[i]=inf;
  51. while(1)
  52. {
  53. memset(visx,0,sizeof(visx));
  54. memset(visy,0,sizeof(visy));
  55. if(DFS(x))break;
  56. int d=inf;
  57. for(int i=1;i<=ny;i++)
  58. {
  59. if(!visy[i]&&d>slack[i])
  60. d=slack[i];
  61. }
  62. for(int i=1;i<=nx;i++)
  63. {
  64. if(visx[i])
  65. lx[i]-=d;
  66. }
  67. for(int i=1;i<=ny;i++)
  68. {
  69. if(visy[i])
  70. ly[i]+=d;
  71. else
  72. slack[i]-=d;
  73. }
  74. }
  75. }
  76. int res=0;
  77. for(int i=1;i<=ny;i++)
  78. {
  79. if(link[i]>-1)
  80. res+=w[link[i]][i];
  81. }
  82. return res;
  83. }
  84. int main()
  85. {
  86. while(~scanf("%d",&n))
  87. {
  88. for(int i=1;i<=n;i++)
  89. {
  90. for(int j=1;j<=n;j++)
  91. {
  92. scanf("%d",&w[i][j]);
  93. }
  94. }
  95. nx=n,ny=n;
  96. int ans=KM();
  97. // printf("KM=%d\n",ans);
  98. int sum=0;
  99. for(int i=1;i<=n;i++)
  100. {
  101. printf("%d%c",lx[i]," \n"[i==n]);
  102. sum+=lx[i];
  103. }
  104. for(int i=1;i<=n;i++)
  105. {
  106. printf("%d%c",ly[i]," \n"[i==n]);
  107. sum+=ly[i];
  108. }
  109. printf("%d\n",sum);
  110. }
  111. return 0;
  112. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注