UVa 11383 少林决胜(二分图最佳完美匹配)

https://vjudge.net/problem/UVA-11383

题意:

给定一个N×N矩阵,每个格子里都有一个正整数W(i,j)。你的任务是给每行确定一个整数row(i),每列也确定一个整数col(i),使得对于任意格子(i,j),w(i,j)<=row(i)+col(j)。所有的row(i)和col(i)只和应尽量小。

思路:

利用二分图最佳完美匹配当中的l(x)+l(y)>=w(i,j),直接用KM算法即可。

  1 #include<iostream>
  2 #include<string>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<cstdio>
  7 using namespace std;
  8 const int maxn=500+5;
  9 
 10 int W[maxn][maxn], n;
 11 int Lx[maxn];
 12 int Ly[maxn];
 13 int Left[maxn];
 14 bool S[maxn], T[maxn];
 15 
 16 bool Match(int i)
 17 {
 18     S[i] = true;
 19     for (int j = 1; j <= n; j++)
 20     {
 21         if (Lx[i] + Ly[j] == W[i][j] && !T[j])
 22         {
 23             T[j] = true;
 24             if (!Left[j] || Match(Left[j]))
 25             {
 26                 Left[j] = i;
 27                 return true;
 28             }
 29         }
 30     }
 31     return false;
 32 }
 33 
 34 void Update()
 35 {
 36     int a = 1 << 30;
 37     for (int i = 1; i <= n; i++)
 38     {
 39         if (S[i])
 40         {
 41             for (int j = 1; j <= n; j++)
 42             {
 43                 if (!T[j])
 44                 {
 45                     a = min(a, Lx[i] + Ly[j] - W[i][j]);
 46                 }
 47             }
 48         }
 49     }
 50     for (int i = 1; i <= n; i++)
 51     {
 52         if (S[i])
 53             Lx[i] -= a;
 54         if (T[i])
 55             Ly[i] += a;
 56     }
 57 }
 58 
 59 void KM()
 60 {
 61     for (int i = 1; i <= n; i++)
 62     {
 63         Left[i] = 0;
 64         Lx[i] = 0;
 65         Ly[i] = 0;
 66         for (int j = 1; j <= n; j++)
 67         {
 68             Lx[i] = max(Lx[i], W[i][j]);
 69         }
 70     }
 71     for (int i = 1; i <= n; i++)
 72     {
 73         while (true)
 74         {
 75             memset(S, 0, sizeof(S));
 76             memset(T, 0, sizeof(T));
 77             if (Match(i))
 78                 break;
 79             else
 80                 Update();
 81         }
 82     }
 83 }
 84 
 85 int main()
 86 {
 87     //freopen("D:\input.txt","r",stdin);
 88     while(~scanf("%d",&n))
 89     {
 90         for(int i=1;i<=n;i++)
 91         {
 92             for(int j=1;j<=n;j++)
 93                 scanf("%d",&W[i][j]);
 94         }
 95         int ans=0;
 96         KM();
 97         for(int i=1;i<=n;i++)
 98         {
 99             printf("%d%c", Lx[i], i == n ? '
' : ' ');
100             ans+=Lx[i];
101         }
102         for(int i=1;i<=n;i++)
103         {
104              printf("%d%c", Ly[i], i == n ? '
' : ' ');
105             ans+=Ly[i];
106         }
107         printf("%d
",ans);
108     }
109     return 0;
110 }
原文地址:https://www.cnblogs.com/zyb993963526/p/6883944.html