题目链接:https://vjudge.net/problem/UVA-11383
题解:
根据KM()算法,标杆满足:l(x) + l(y) >= w(x, y) 。
当求完最大权匹配之后,所有标杆在满足:l(x) + l(y) >= w(x, y) 的条件下,和最小。
代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int INF = 2e9; 5 const LL LNF = 9e18; 6 const int mod = 1e9+7; 7 const int MAXN = 500+10; 8 9 int nx, ny; 10 int g[MAXN][MAXN], linker[MAXN], lx[MAXN], ly[MAXN], slack[MAXN]; 11 bool visx[MAXN], visy[MAXN]; 12 13 bool DFS(int x) 14 { 15 visx[x] = true; 16 for(int y = 1; y<=ny; y++) 17 { 18 if(visy[y]) continue; 19 int tmp = lx[x] + ly[y] - g[x][y]; 20 if(tmp==0) 21 { 22 visy[y] = true; 23 if(linker[y]==-1 || DFS(linker[y])) 24 { 25 linker[y] = x; 26 return true; 27 } 28 } 29 else 30 slack[y] = min(slack[y], tmp); 31 } 32 return false; 33 } 34 35 void KM() 36 { 37 memset(linker, -1, sizeof(linker)); 38 memset(ly, 0, sizeof(ly)); 39 for(int i = 1; i<=nx; i++) 40 { 41 lx[i] = -INF; 42 for(int j = 1; j<=ny; j++) 43 lx[i] = max(lx[i], g[i][j]); 44 } 45 46 for(int x = 1; x<=nx; x++) 47 { 48 for(int i = 1; i<=ny; i++) 49 slack[i] = INF; 50 while(true) 51 { 52 memset(visx, 0, sizeof(visx)); 53 memset(visy, 0, sizeof(visy)); 54 55 if(DFS(x)) break; 56 int d = INF; 57 for(int i = 1; i<=ny; i++) 58 if(!visy[i]) 59 d = min(d, slack[i]); 60 61 for(int i = 1; i<=nx; i++) 62 if(visx[i]) 63 lx[i] -= d; 64 for(int i = 1; i<=ny; i++) 65 { 66 if(visy[i]) ly[i] += d; 67 else slack[i] -= d; 68 } 69 } 70 } 71 } 72 73 int main() 74 { 75 int n; 76 while(scanf("%d",&n)!=EOF) 77 { 78 nx = ny = n; 79 for(int i = 1; i<=nx; i++) 80 for(int j = 1; j<=ny; j++) 81 scanf("%d",&g[i][j]); 82 83 KM(); 84 int sum = 0; 85 for(int i = 1; i<=nx; i++) printf("%d ", lx[i]), sum += lx[i]; 86 printf(" "); 87 for(int i = 1; i<=ny; i++) printf("%d ", ly[i]), sum += ly[i]; 88 printf(" "); 89 printf("%d ", sum); 90 } 91 }