Hacker Country
Difficulty: Hard

There are *N* cities in *Hacker Country*. Each pair of cities are directly connected by a unique directed road, and each road has its own toll that must be paid every time it is used. You're planning a road trip in *Hacker Country*, and its itinerary must satisfy the following conditions:  

+ You can start in any city.
+ You must use $2$ or more different roads (meaning you will visit $2$ or more cities).
+ At the end of your trip, you should be back in your city of origin.
+ The average cost (sum of tolls paid per road traveled) should be minimum.

Can you calculate the *minimum average cost* of a trip in *Hacker Country*?

**Time Limits**  
Time limits for this challenge are provided [here](https://www.hackerrank.com/environment).

Input Format:
The first line is an integer, $N$ (number of cities).  
The $N$ subsequent lines of  $N$ space-separated integers each describe the respective tolls or traveling from city $i$ to city $j$; in other words, the $j^{th}$ integer of the $i^{th}$ line denotes the toll for traveling from city $i$ to city $j$.  

**Note:** As there are no roads connecting a city to itself, the $i^{th}$ integer of line $i$ will always be $0$.

**Constraints**  
$1 \lt N \leq 500$  
$0 \lt toll \ cost \leq 200$  
$roads \ traveled \geq 2$

Output Format:
Print the *minimum cost* as a rational number $p \ / \ q$ (tolls paid over roads traveled). The *greatest common divisor* of $p$ and $q$ should be $1$. 

Sample Input:
    2
    0 1
    2 0

Sample Output:
    3/2

Python 3 starter code:
#
# Complete the 'hackerCountry' function below.
#
# The function is expected to return a STRING.
# The function accepts 2D_INTEGER_ARRAY tolls as parameter.
#

def hackerCountry(tolls):
    # Write your code here



Editorial: Hacker Country : Codesprint 5 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><a href="https://www.hackerrank.com/contests/codesprint5/challenges/hacker-country">Hacker Country</a></p>

<p><strong>Difficulty Level</strong> : Easy-Hard <br>
<strong>Required Knowledge</strong> : Directed Cycles, minimum mean length <br>
<strong>Problem Setter</strong> : <a href="https://www.hackerrank.com/cpcs">Cao Peng</a> <br>
<strong>Problem Tester</strong> : <a href="https://www.hackerrank.com/dsoboliev">Dmytro Soboliev</a></p>

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

<p>The approach for this problem is explained <a href="https://hr-filepicker.s3.amazonaws.com/perfect-country.pdf">here</a></p>

<p><strong>Setter's Code</strong></p>

<pre><code>#include &lt;cstdio&gt;
#include &lt;cstring&gt;
#include &lt;cassert&gt;
#include &lt;algorithm&gt;


using namespace std;

const int N = 505;

int  d[N][N],a[N][N];

int cmp(const pair&lt;int,int&gt; &amp;a,const pair&lt;int,int&gt; &amp;b) { // a - b
    return a.first * b.second - a.second * b.first;
}

int gcd(int a,int b){
    return b?gcd(b,a%b):a;
}



int main() {
int n;
    scanf("%d",&amp;n);
    assert((n &gt; 1) &amp;&amp; (n &lt;= 500));
    for (int i = 0; i &lt; n; ++i) {
        for (int j = 0; j &lt; n; ++j) {
            scanf("%d",&amp;a[i][j]);
            if (i == j) {
                assert(a[i][j] == 0);
            }
            else {
                assert((a[i][j] &gt; 0) &amp;&amp; (a[i][j] &lt;= 200));
            }
        }
    }

    // d[i + 1][j] = min(d[i][k] + a[k][j])

    for (int i = 0; i &lt; n; ++i) {
        for (int j = 0; j &lt; n; ++j) {
            bool mark = false;
            for (int k = 0; k &lt; n; ++k) {
                if (k != j) {
                    if (mark) {
                        d[i + 1][j] = min(d[i + 1][j] , d[i][k] + a[k][j]);
                    }
                    else {
                        mark = true;
                        d[i + 1][j]  = d[i][k] + a[k][j];
                    }
                }
            }
        }

    }

    pair&lt;int,int&gt; answer; 
    // answer = min max  (d[n][i] - d[k][i]) / (n - k)
    for (int i = 0; i &lt; n; ++i) {
        pair&lt;int,int&gt; now = make_pair(d[n][i] - d[0][i], n);
        for (int k = 1; k &lt; n; ++k) {
            pair&lt;int,int&gt; temp = make_pair(d[n][i] - d[k][i], n - k);
            if (cmp(temp, now) &gt; 0) {
                now = temp;
            }
        }
        if ((i == 0) || (cmp(now, answer) &lt; 0)) {
            answer = now;
        }
    }
    int g = gcd(answer.first, answer.second);
    printf("%d/%d\n",answer.first / g, answer.second / g);
    return 0;
}
</code></pre>

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

<pre><code>#include &lt;iostream&gt;
#include &lt;cstdio&gt;

using namespace std;

const int maxN = 600;
const int inf = 1000000000;
int g[maxN][maxN], d[maxN][maxN];
int n;

long long gcd(long long a, long long b) {
    if (a == 0 || b == 0) {
        return a + b;
    }
    if (a &gt; b) {
        return gcd(a % b, b);
    } else {
        return gcd(b % a, a);
    }
}

int main() {
    scanf("%d", &amp;n);
    for (int i = 0; i &lt; n; ++i) {
        for (int j = 0; j &lt; n; ++j) {
            scanf("%d", &amp;g[i][j]);
        }
    }

    for (int i = 1; i &lt;= n; ++i) {
        for (int j = 0; j &lt; n; ++j) {
            int best = inf;
            for (int k = 0; k &lt; n; ++k) {
                if (j != k) {
                    best = min(best, d[i - 1][k] + g[k][j]);
                }
            }
            d[i][j] = best;
        }
    }

    long long p = inf, q = 1;
    for (int i = 0; i &lt; n; ++i) {
        long long a = 0, b = 1;
        for (int j = 0; j &lt; n; ++j) {
            long long c = d[n][i] - d[j][i];
            long long d = n - j;

            if (c * b &gt; a * d) {
                a = c;
                b = d;
            }
        }

        if (a * q &lt; b * p) {
            p = a;
            q = b;
        }
    }

    long long d = gcd(p, q);
    p /= d;
    q /= d;

    cout &lt;&lt; p &lt;&lt; "/" &lt;&lt; q &lt;&lt; endl;

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

Reference solution (C++):
###C++  
```cpp  
#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
    
    
using namespace std;
    
const int N = 505;
    
int  d[N][N],a[N][N];
    
int cmp(const pair<int,int> &a,const pair<int,int> &b) { // a - b
    return a.first * b.second - a.second * b.first;
}
    
int gcd(int a,int b){
    return b?gcd(b,a%b):a;
}
    
    
    
int main() {
int n;
    scanf("%d",&n);
    assert((n > 1) && (n <= 500));
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            scanf("%d",&a[i][j]);
            if (i == j) {
                assert(a[i][j] == 0);
            }
            else {
                assert((a[i][j] > 0) && (a[i][j] <= 200));
            }
        }
    }
    
    // d[i + 1][j] = min(d[i][k] + a[k][j])
        
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            bool mark = false;
            for (int k = 0; k < n; ++k) {
                if (k != j) {
                    if (mark) {
                        d[i + 1][j] = min(d[i + 1][j] , d[i][k] + a[k][j]);
                    }
                    else {
                        mark = true;
                        d[i + 1][j]  = d[i][k] + a[k][j];
                    }
                }
            }
        }
    
    }
    
    pair<int,int> answer; 
    // answer = min max  (d[n][i] - d[k][i]) / (n - k)
    for (int i = 0; i < n; ++i) {
        pair<int,int> now = make_pair(d[n][i] - d[0][i], n);
        for (int k = 1; k < n; ++k) {
            pair<int,int> temp = make_pair(d[n][i] - d[k][i], n - k);
            if (cmp(temp, now) > 0) {
                now = temp;
            }
        }
        if ((i == 0) || (cmp(now, answer) < 0)) {
            answer = now;
        }
    }
    int g = gcd(answer.first, answer.second);
    printf("%d/%d\n",answer.first / g, answer.second / g);
    return 0;
}
    
```