Bike Racers
Difficulty: Hard


There are $N$ bikers present in a city (shaped as a grid) having $M$ bikes. All the bikers want to participate in the HackerRace competition, but unfortunately only $K$ bikers can be accommodated in the race. Jack is organizing the HackerRace and wants to start the race as soon as possible. He can instruct any biker to move towards any bike in the city. In order to minimize the time to start the race, Jack instructs the bikers in such a way that the first $K$ bikes are acquired in the minimum time.

Every biker moves with a unit speed and one bike can be acquired by only one biker. *A biker can proceed in any direction*. Consider distance between bikes and bikers as Euclidean distance.

Jack would like to know the *square of required time* to start the race as soon as possible. 


Input Format:
The first line contains three integers, $N$, $M$, and $K$, separated by a single space.  
The following $N$ lines will contain $N$ pairs of integers denoting the co-ordinates of $N$ bikers. Each pair of integers is separated by a single space. The next $M$ lines will similarly denote the co-ordinates of the $M$ bikes.


Output Format:
A single line containing the square of required time.


Sample Input:
    3 3 2
    0 1
    0 2
    0 3
    100 1
    200 2 
    300 3


Sample Output:
    40000


Python 3 starter code:
#
# Complete the 'bikeRacers' function below.
#
# The function is expected to return a LONG_INTEGER.
# The function accepts following parameters:
#  1. 2D_INTEGER_ARRAY bikers
#  2. 2D_INTEGER_ARRAY bikes
#

def bikeRacers(bikers, bikes):
    # Write your code here



Editorial: Bike Racers - 2020 Hack February Editorial
<style id="MathJax_SVG_styles">.MathJax_SVG_Display {text-align: center; margin: 1em 0em; position: relative; display: block!important; text-indent: 0; max-width: none; max-height: none; min-width: 0; min-height: 0; width: 100%}
.MathJax_SVG .MJX-monospace {font-family: monospace}
.MathJax_SVG .MJX-sans-serif {font-family: sans-serif}
.MathJax_SVG {display: inline; font-style: normal; font-weight: normal; line-height: normal; font-size: 100%; font-size-adjust: none; text-indent: 0; text-align: left; text-transform: none; letter-spacing: normal; word-spacing: normal; word-wrap: normal; white-space: nowrap; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0; min-height: 0; border: 0; padding: 0; margin: 0}
.MathJax_SVG * {transition: none; -webkit-transition: none; -moz-transition: none; -ms-transition: none; -o-transition: none}
.mjx-svg-href {fill: blue; stroke: blue}
</style><svg style="display: none;"><defs id="MathJax_SVG_glyphs"></defs></svg><p><strong>Problem</strong> :  Tell the time by which K bikers will get bike. Read full problem <a href="https://www.hackerrank.com/contests/feb14/challenges/bike-racers">here</a>  </p>

<p><strong>Required Knowledge</strong> : Binary Search, Bipartite Matching . </p>

<p><strong>Time Complexity</strong> : O(K^2 * log(10^14 )  ) </p>

<p><strong>Approach</strong> :</p>

<p>This is a problem for which you have to solve 2 <strong>subproblems</strong>, each subproblem will help you in learning some useful concept.</p>

<p><strong>Subproblem 1</strong> First try to solve a problem, Given N bikes and M bikers and time T, How many bikers (at max) will be get a bike ? while each bikers can have only one bike and one bike can be accommodated by only one biker.<br></p>

<p><strong>Solution</strong> :  Make a bipartite graph, Having N node in one partite and having M nove in other partite and connect a node X from first partite to a node Y of second partite iff bike Y is reachable from biker X is given amount of time T.</p>

<p><strong>Value of maxium bipartite matching is the solution of subproblem 1</strong></p>

<p>Now using this subproblem we can check whether in given amount of Time whether K bikers can get bike or not.</p>

<p>Now define a function f in given manner</p>

<p><strong>f(T)</strong> = true  if K bikers can get in bike in square_root(T) time.<br>
           else false.</p>

<p>as it is very obvious that if <strong>f(T) = true</strong> then <strong>f(T1) = true</strong> for all T1&gt;=T.</p>

<p>and f(0) = false and f(10^16) = true. as all co-ordinates X,Y &lt;= 10^7<br>
Now we can use classical binary search to get the value of exact value of T.</p>

<p><strong>Subproblem 2</strong> : Binary search can solved using the classical method.<br></p>

<pre><code>long long int low = 0;
long long int high = 10000000000000000;

while(low &lt; high)
{
long long int mid = (low + high) / 2;
if( f( mid ) )
{
high = mid;
}
else
{
low = mid+1 ;
}

}
</code></pre>

<p>Which will give the precise value of <strong>Square of Time</strong>.</p>

<p><strong>Setter's code</strong> :</p>

<pre><code>//Hopcraft carp maxium matching algorithm time complexity = E*sqrt(V)

#include&lt;iostream&gt;
#include&lt;cstdlib&gt;
#include &lt;cstdio&gt;
#include &lt;queue&gt;
#include &lt;vector&gt;
#include&lt;bits/stdc++.h&gt;
using namespace std;
#define SET(x) memset(x, -1, sizeof(x))
#define CLR(x) memset(x, 0, sizeof(x))
#define MAX 2001
#define NIL 0
#define INF (1&lt;&lt;28)

int N,M,K;

vector&lt; int &gt; edges[MAX]; // edges of left side
bool visited[MAX];
int Left[MAX], Right[MAX];
long long int dist[MAX][MAX];

bool dfs(int u) {
    if(visited[u]) return false;
    visited[u] = true;
    int len = edges[u].size(), i, v;
    for(i=0; i&lt;len; i++) {
        v = edges[u][i];
        if(Right[v]==-1) {
            Right[v] = u, Left[u] = v;
            return true;
        }
    }
    for(i=0; i&lt;len; i++) {
        v = edges[u][i];
        if(dfs(Right[v])) {
            Right[v] = u, Left[u] = v;
            return true;
        }
    }
    return false;
}

int match() {
    SET(Left); // left = -1
    SET(Right); // right = -1
    int i, ret = 0;
    bool done;
    do {
        done = true;
        CLR(visited); // visited = 0
        for(i=1; i&lt;=N; i++) {
            if(Left[i]==-1 &amp;&amp; dfs(i)) {
                done = false;
            }
        }
    } while(!done);
    for(i=1; i&lt;=N; i++) ret += (Left[i]!=-1);
    return ret;
}

bool check ( long long int val)
{
    for(int i=1 ; i&lt;=N ; i++)
{
for( int j=1 ; j&lt;=M ; j++)
{
if(dist[i][j] &lt;=val)
{
edges[i].push_back(j);
}
}
}

long long int num_match = match();

for(int i= 1 ; i&lt;= N ; i++)
edges[i].clear();

if(num_match &gt;=K)
return true;
else
return false;

}

int main()
{
cin&gt;&gt;N&gt;&gt;M&gt;&gt;K;
    assert(K &lt;= N);
    assert(K &lt;= M);
int a,b;
pair&lt;long long int,long long int&gt; P[N+1];
pair&lt;long long int,long long int&gt; Q[M+1];
for(int i=1 ; i&lt;=N; i++)
cin&gt;&gt;P[i].first&gt;&gt;P[i].second;
for(int i=1 ; i&lt;=M ; i++)
cin&gt;&gt;Q[i].first&gt;&gt;Q[i].second;
for(int i=1 ; i&lt;=N ; i++)
{
for(int j=1 ; j&lt;=M ; j++)
{
dist[i][j] = (P[i].first - Q[j].first)*(P[i].first - Q[j].first) + (P[i].second - Q[j].second)*(P[i].second - Q[j].second);
}
}   

long long int low = 0;
long long int high = 10000000000000000;

while(low &lt; high)
{
long long int mid = (low + high) / 2;
if( check( mid ) )
{
high = mid;
}
else
{
low = mid+1 ;
}

}
cout&lt;&lt;low&lt;&lt;endl;
return 0;
}
</code></pre>

<p><strong>Tester's Code</strong> :</p>

<pre><code>#include &lt;bits/stdc++.h&gt;
using namespace std;

const int sz = 2000;

long long userX[sz], userY[sz];
long long bikeX[sz], bikeY[sz];
int lt[sz];
int N, M, K;
bool vis[sz];

bool validPath(int userId, int bikerId, long long distanceAllowed) {
    long long distX = userX[userId] - bikeX[bikerId];
    distX *= distX;
    long long distY = userY[userId] - bikeY[bikerId];
    distY *= distY;

    return distX + distY &lt;= distanceAllowed;
}

bool dfs(int u, long long distanceAllowed) {
    if(u == -1)
        return true;
    if(vis[u])
        return false;
    vis[u] = true;

    for(int i = 0; i &lt; (int)M; ++i) {
        int id = lt[i];
        if(validPath(u, i, distanceAllowed) &amp;&amp; dfs(id, distanceAllowed)) {
            lt[i] = u;
            return true;
        }
    }
    return false;
}

int matching(long long tm) {
    memset(lt, -1, sizeof(lt));

    int ret = 0;
    for(int i = 0; i &lt; (int)N; ++i) {
        memset(vis, 0, sizeof(vis));
        if(dfs(i, tm))
            ret++;
    }
    return ret;
}

long long binarySearch(long long l = 0, long long r = 1e17) {
    if(l == r)
        return l;
    long long mid = (l+r)/2;
    int match = matching(mid);
    return match &gt;= K ? binarySearch(l, mid) : binarySearch(mid+1, r);
}

int main()
{
    cin &gt;&gt; N &gt;&gt; M &gt;&gt; K;
    assert(1 &lt;= N); assert(N &lt;= sz);
    assert(1 &lt;= M); assert(M &lt;= sz);
    assert(1 &lt;= K); assert(K &lt;= min(N, M));

    for(int i = 0; i &lt; (int)N; ++i) {
        cin &gt;&gt; userX[i] &gt;&gt; userY[i];
        assert(0 &lt;= userX[i]); assert(userX[i] &lt;= 1e7);
        assert(0 &lt;= userY[i]); assert(userY[i] &lt;= 1e7);
    }
    for(int i = 0; i &lt; (int)M; ++i) {
        cin &gt;&gt; bikeX[i] &gt;&gt; bikeY[i];
        assert(0 &lt;= bikeX[i]); assert(bikeX[i] &lt;= 1e7);
        assert(0 &lt;= bikeY[i]); assert(bikeY[i] &lt;= 1e7);
    }

    cout &lt;&lt; binarySearch() &lt;&lt; endl;

    return 0;
}
</code></pre>

Reference solution (C++):
###C++  
```cpp  

//Hopcraft carp maxium matching algorithm time complexity = E*sqrt(V)
    
#include<iostream>
#include<cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include<bits/stdc++.h>
using namespace std;
#define SET(x) memset(x, -1, sizeof(x))
#define CLR(x) memset(x, 0, sizeof(x))
#define MAX 2001
#define NIL 0
#define INF (1<<28)
    
int N,M,K;
    
vector< int > edges[MAX]; // edges of left side
bool visited[MAX];
int Left[MAX], Right[MAX];
long long int dist[MAX][MAX];
    
bool dfs(int u) {
    if(visited[u]) return false;
    visited[u] = true;
    int len = edges[u].size(), i, v;
    for(i=0; i<len; i++) {
        v = edges[u][i];
        if(Right[v]==-1) {
            Right[v] = u, Left[u] = v;
            return true;
        }
    }
    for(i=0; i<len; i++) {
        v = edges[u][i];
        if(dfs(Right[v])) {
            Right[v] = u, Left[u] = v;
            return true;
        }
    }
    return false;
}
    
int match() {
    SET(Left); // left = -1
    SET(Right); // right = -1
    int i, ret = 0;
    bool done;
    do {
        done = true;
        CLR(visited); // visited = 0
        for(i=1; i<=N; i++) {
            if(Left[i]==-1 && dfs(i)) {
                done = false;
            }
        }
    } while(!done);
    for(i=1; i<=N; i++) ret += (Left[i]!=-1);
    return ret;
}
    
bool check ( long long int val) {
    for(int i=1 ; i<=N ; i++) {
        for( int j=1 ; j<=M ; j++) {
            if(dist[i][j] <=val) {
                edges[i].push_back(j);
            }
        }
    }
    
    long long int num_match = match();
    
    for(int i= 1 ; i<= N ; i++)
        edges[i].clear();
    
    if(num_match >=K)
        return true;
    else
        return false;
}
    
int main() {
    cin>>N>>M>>K;
    int a,b;
    pair<long long int,long long int> P[N+1];
    pair<long long int,long long int> 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;
    for(int i=1 ; i<=N ; i++) {
        for(int j=1 ; j<=M ; j++) {
            dist[i][j] = (P[i].first - Q[j].first)
                        *(P[i].first - Q[j].first)
                        + (P[i].second - Q[j].second)
                        *(P[i].second - Q[j].second);
        }
    }    

    long long int low = 0;
    long long int high = 10000000000000000;

    while(low < high) {
        long long int mid = (low + high) / 2;
        if( check( mid ) ) {
            high = mid;
        } else {
            low = mid+1 ;
        }
    }
    cout << low << endl;
    return 0;
}
```