Const int max = 1e6 + 10;
Const int INF = 0x3f3f3f;
Int n, m;
Int lx [Max], Ly [Max];
Int match [Max];
Int usex [Max], usey [Max];
Int W [Max] [Max];
Int find (int u ){
Usex [u] = 1;
For (INT I = 0; I <m; I ++ ){
If (! Usey [I] & W [u] [I] = ly [I] + lx [u]) {
Usey [I] = 1;
If (Match [I] =-1 | find (Match [I]) {
Match [I] = u;
Return true;
}
}
}
Return false;
}
Void Update (){
Int d = inf;
For (INT I = 0; I <n; I ++) if (usex [I]) {
For (Int J = 0; j <m; j ++) if (! Usey [J]) {
D = min (D, usex [I] + usey [J]-W [I] [J]);
}
}
For (INT I = 0; I <n; I ++) if (usex [I]) lx [I]-= D;
For (INT I = 0; I <m; I ++) if (usey [I]) ly [I] + = D;
}
Int Kuhn (){
Memset (match,-1, sizeof (MATCH ));
For (INT I = 0; I <n; I ++ ){
Lx [I] = ly [I] = 0;
For (Int J = 0; j <m; j ++ ){
Lx [I] = max (LX [I], W [I] [J]);
}
}
For (INT I = 0; I <n; I ++ ){
While (true ){
Memset (usex, 0, sizeof (usex ));
Memset (usey, 0, sizeof (usey ));
If (find (I) break;
Update ();
}
}
}
I tried it by hand. The correctness is not verified.