【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 }

 

posted on 2015-03-15 10:43  Bombe  阅读(136)  评论(0编辑  收藏  举报

导航