The optimal matching of a bipartite graph. Find the minimum billing flow. The minimum cost for matching all vertices is required. simply apply the KM algorithm ..
The following is the 1853 AC code:
[Cpp]
# Include <cstdio>
# Include <cstring>
Using namespace std;
Const int maxn = 305;
Const int INF = (1 <30)-1;
Int g [maxn] [maxn];
Int lx [maxn], ly [maxn];
Int match [maxn];
Bool visx [maxn], visy [maxn];
Int slack [maxn];
Int n;
Bool dfs (int cur ){
Visx [cur] = true;
For (int y = 1; y <= n; y ++ ){
If (visy [y]) continue;
Int t = lx [cur] + ly [y]-g [cur] [y];
If (t = 0 ){
Visy [y] = true;
If (match [y] =-1 | dfs (match [y]) {
Match [y] = cur;
Return true;
}
}
Else if (slack [y]> t ){
Slack [y] = t;
}
}
Return false;
}
Int KM (){
Memset (match,-1, sizeof (match ));
Memset (ly, 0, sizeof (ly ));
For (int I = 1; I <= n; I ++ ){
Lx [I] =-INF;
For (int j = 1; j <= n; j ++)
If (g [I] [j]> lx [I]) lx [I] = g [I] [j];
}
For (int x = 1; x <= n; x ++ ){
For (int I = 1; I <= n; I ++) slack [I] = INF;
While (true ){
Memset (visx, false, sizeof (visx ));
Memset (visy, false, sizeof (visy ));
If (dfs (x) break;
Int d = INF;
For (int I = 1; I <= n; I ++ ){
If (! Visy [I] & d> slack [I]) d = slack [I];
}
For (int I = 1; I <= n; I ++ ){
If (visx [I]) lx [I]-= d;
}
For (int I = 1; I <= n; I ++ ){
If (visy [I]) ly [I] + = d;
Else slack [I]-= d;
}
}
}
Int result = 0;
For (int I = 1; I <= n; I ++ ){
If (match [I] =-1 | g [match [I] [I] =-INF)
Return 1;
If (match [I]>-1)
Result + = g [match [I] [I];
}
Return result;
}
Int main (){
Int m;
Int a, B, c;
While (scanf ("% d", & n, & m )! = EOF ){
Memset (g, 0, sizeof (g ));
For (int I = 1; I <= n; I ++)
For (int j = 1; j <= n; j ++)
G [I] [j] =-INF;
For (int I = 0; I <m; I ++ ){
Scanf ("% d", & a, & B, & c );
If (g [a] [B] <-c)
G [a] [B] =-c;
}
Int ans =-KM ();
Printf ("% d \ n", ans );
}
Return 0;
}
The following code is 3488AC:
[Cpp]
# Include <cstdio>
# Include <cstring>
Using namespace std;
Const int maxn = 205;
Const int INF = (1 <30)-1;
Int g [maxn] [maxn];
Int lx [maxn], ly [maxn];
Int match [maxn];
Bool visx [maxn], visy [maxn];
Int slack [maxn];
Int n;
Bool dfs (int cur ){
Visx [cur] = true;
For (int y = 1; y <= n; y ++ ){
If (visy [y]) continue;
Int t = lx [cur] + ly [y]-g [cur] [y];
If (t = 0 ){
Visy [y] = true;
If (match [y] =-1 | dfs (match [y]) {
Match [y] = cur;
Return true;
}
}
Else if (slack [y]> t ){
Slack [y] = t;
}
}
Return false;
}
Int KM (){
Memset (match,-1, sizeof (match ));
Memset (ly, 0, sizeof (ly ));
For (int I = 1; I <= n; I ++ ){
Lx [I] =-INF;
For (int j = 1; j <= n; j ++)
If (g [I] [j]> lx [I]) lx [I] = g [I] [j];
}
For (int x = 1; x <= n; x ++ ){
For (int I = 1; I <= n; I ++) slack [I] = INF;
While (true ){
Memset (visx, false, sizeof (visx ));
Memset (visy, false, sizeof (visy ));
If (dfs (x) break;
Int d = INF;
For (int I = 1; I <= n; I ++ ){
If (! Visy [I] & d> slack [I]) d = slack [I];
}
For (int I = 1; I <= n; I ++ ){
If (visx [I]) lx [I]-= d;
}
For (int I = 1; I <= n; I ++ ){
If (visy [I]) ly [I] + = d;
Else slack [I]-= d;
}
}
}
Int result = 0;
For (int I = 1; I <= n; I ++ ){
If (match [I] =-1 | g [match [I] [I] =-INF)
Return 1;
If (match [I]>-1)
Result + = g [match [I] [I];
}
Return result;
}
Int main (){
Int m, T;
Int a, B, c;
Scanf ("% d", & T );
While (T --){
Scanf ("% d", & n, & m );
Memset (g, 0, sizeof (g ));
For (int I = 1; I <= n; I ++)
For (int j = 1; j <= n; j ++)
G [I] [j] =-INF;
For (int I = 0; I <m; I ++ ){
Scanf ("% d", & a, & B, & c );
If (g [a] [B] <-c)
G [a] [B] =-c;
}
Int ans =-KM ();
Printf ("% d \ n", ans );
}
Return 0;
}
The following is the 3435 AC code:
[Cpp]
# Include <cstdio>
# Include <cstring>
Using namespace std;
Const int maxn = 1005;
Const int INF = (1 <30)-1;
Int g [maxn] [maxn];
Int lx [maxn], ly [maxn];
Int match [maxn];
Bool visx [maxn], visy [maxn];
Int slack [maxn];
Int n;
Bool dfs (int cur ){
Visx [cur] = true;
For (int y = 1; y <= n; y ++ ){
If (visy [y]) continue;
Int t = lx [cur] + ly [y]-g [cur] [y];
If (t = 0 ){
Visy [y] = true;
If (match [y] =-1 | dfs (match [y]) {
Match [y] = cur;
Return true;
}
}
Else if (slack [y]> t ){
Slack [y] = t;
}
}
Return false;
}
Int KM (){
Memset (match,-1, sizeof (match ));
Memset (ly, 0, sizeof (ly ));
For (int I = 1; I <= n; I ++ ){
Lx [I] =-INF;
For (int j = 1; j <= n; j ++)
If (g [I] [j]> lx [I]) lx [I] = g [I] [j];
}
For (int x = 1; x <= n; x ++ ){
For (int I = 1; I <= n; I ++) slack [I] = INF;
While (true ){
Memset (visx, false, sizeof (visx ));
Memset (visy, false, sizeof (visy ));
If (dfs (x) break;
Int d = INF;
For (int I = 1; I <= n; I ++ ){
If (! Visy [I] & d> slack [I]) d = slack [I];
}
For (int I = 1; I <= n; I ++ ){
If (visx [I]) lx [I]-= d;
}
For (int I = 1; I <= n; I ++ ){
If (visy [I]) ly [I] + = d;
Else slack [I]-= d;
}
}
}
Int result = 0;
For (int I = 1; I <= n; I ++ ){
If (match [I] =-1 | g [match [I] [I] =-INF)
Return 1;
If (match [I]>-1)
Result + = g [match [I] [I];
}
Return result;
}
Int main (){
Int m, T, ca = 1;
Int a, B, c;
Scanf ("% d", & T );
While (T --){
Scanf ("% d", & n, & m );
Memset (g, 0, sizeof (g ));
For (int I = 1; I <= n; I ++)
For (int j = 1; j <= n; j ++)
G [I] [j] =-INF;
For (int I = 0; I <m; I ++ ){
Scanf ("% d", & a, & B, & c );
If (g [a] [B] <-c)
G [a] [B] =-c;
If (g [B] [a] <-c)
G [B] [a] =-c;
}
Int ans =-KM ();
If (ans =-1)
Printf ("Case % d: NO \ n", ca ++ );
Else
Printf ("Case % d: % d \ n", ca ++, ans );
}
Return 0;
}