Just for study from its editorial~
Lesson learnt: an optimized Hungarian Algorithm: Hopcroft-Karp Algorithm (a batched version of Hungarian)
A very good article on it (in Chinese): https://www.renfei.org/blog/bipartite-matching.html
The basic idea of Hungarian is: find all augment pathes and flip (matchedunmatched toggled) them, recursively.
And Hopcroft-Karp is a batched version of Hungarian: we simply check all edges at each node.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cmath> #include <cstdio> #include <vector> #include <queue> #include <iostream> #include <algorithm> #include <unordered_map> #include <unordered_set> using namespace std; #define MAX 2001 typedef long long LL; int N, M, K; vector<int> edges[MAX]; // edges of left side vector<bool> visited(MAX); vector<int> Left(MAX), Right(MAX); vector<vector<LL>> dist(MAX, vector<LL>(MAX)); /* * Hopcroft-Karp Algorithm: optimized(batched) Hungarian Algorithm * Complexity: E*sqrt(V) */ // True: augment path flipped // False:augment path stay the same // bool dfs(int u) { if(visited[u]) return false; visited[u] = true; // Flip input u-v pairs for(auto v : edges[u]) { if(Right[v] == -1) // u-v not matched { // then match u-v Right[v] = u, Left[u] = v; return true; } } // Given all input u-v are matched then match deeper pathes for(auto v : edges[u]) { if(dfs(Right[v])) // flipped deeper? { // then flip current edge too Right[v] = u, Left[u] = v; return true; } } return false; } int match() { // Cleanup work Left.assign(MAX, -1); Right.assign(MAX, -1); int i, ret = 0; bool done = true; do { done = true; // for the new aug. path visited.assign(MAX, 0); for(int i = 1; i <= N; i ++) if(Left[i] == -1 && dfs(i)) done = false; // augment-able? again.. }while(!done); // Count no. of matched edges for(int i = 1; i <= N; i ++) ret += Left[i] != -1; return ret; } /**********************************************/ bool check(LL val) { // Pick reasonable edges for( int i=1 ; i<=N ; i++) for( int j=1 ; j<=M ; j++) if(dist[i][j] <= val) edges[i].push_back(j); // Run Hopcroft-Karp LL num_match = match(); // Clean for the next check for(int i= 1 ; i<= N ; i++) edges[i].clear(); return num_match >= K; } int main() { cin >> N >> M >> K; // Get input array vector<pair<LL, LL>> P(N + 1), Q(M + 1); for(int i = 1; i <= N; i ++) cin >> P[i].first >> P[i].second; for(int i = 1; i <= M; i ++) cin >> Q[i].first >> Q[i].second; // Calculate distances for(int i=1 ; i<=N ; i++) for(int j=1 ; j<=M ; j++) { LL a = P[i].first - Q[j].first; LL b = P[i].second - Q[j].second; dist[i][j] = a * a + b * b; } // Binay Search the min matching result for K LL low = 0, high = 10000000000000000; while(low < high) { LL mid = (low + high) >> 1; if(check(mid)) high = mid; else low = mid + 1; } cout << low << endl; return 0; }