【HDOJ】2255 奔小康赚大钱
最大二分图匹配,O(n^3)。
1 /* 2255 */ 2 #include <iostream> 3 #include <algorithm> 4 #include <cstdio> 5 #include <cstring> 6 #include <cstdlib> 7 using namespace std; 8 9 #define MAXN 305 10 #define INF 0x3f3f3f3f 11 12 int w[MAXN][MAXN]; 13 int link[MAXN]; 14 int Lx[MAXN], Ly[MAXN]; 15 int slack[MAXN]; 16 bool S[MAXN], T[MAXN]; 17 int n; 18 19 bool dfs(int i) { 20 S[i] = true; 21 for (int j=1; j<=n; ++j) { 22 if (T[j]) 23 continue; 24 int tmp = Lx[i]+Ly[j]-w[i][j]; 25 if (tmp == 0) { 26 T[j] = true; 27 if (!link[j] || dfs(link[j])) { 28 link[j] = i; 29 return true; 30 } 31 } else { 32 slack[j] = min(slack[j], tmp); 33 } 34 } 35 return false; 36 } 37 38 void update() { 39 int mn = INF; 40 for (int i=1; i<=n; ++i) if (!T[i]) mn = min(mn, slack[i]); 41 for (int i=1; i<=n; ++i) { 42 if (S[i]) Lx[i] -= mn; 43 if (T[i]) Ly[i] += mn; 44 } 45 } 46 47 void KM() { 48 int i, j, k; 49 50 memset(link, 0, sizeof(link)); 51 memset(Lx, 0, sizeof(Lx)); 52 memset(Ly, 0, sizeof(Ly)); 53 for (i=1; i<=n; ++i) 54 for (j=1; j<=n; ++j) 55 Lx[i] = max(Lx[i], w[i][j]); 56 for (i=1; i<=n; ++i) { 57 for (;;) { 58 memset(S, false, sizeof(S)); 59 memset(T, false, sizeof(T)); 60 memset(slack, INF, sizeof(slack)); 61 if (dfs(i)) 62 break; 63 else 64 update(); 65 } 66 } 67 } 68 69 int main() { 70 int i, j, k; 71 int ans; 72 73 #ifndef ONLINE_JUDGE 74 freopen("data.in", "r", stdin); 75 freopen("data.out", "w", stdout); 76 #endif 77 78 while (scanf("%d",&n)!=EOF) { 79 for (i=1; i<=n; ++i) 80 for (j=1; j<=n; ++j) 81 scanf("%d", &w[i][j]); 82 KM(); 83 for (ans=0,i=1; i<=n; ++i) 84 if (link[i]) 85 ans += w[link[i]][i]; 86 printf("%d\n", ans); 87 } 88 89 return 0; 90 }