// for input:
// 3
// 10.7 8 18.9
// 6.6 11.2 13.7
// 14.1 13.8 9.4
//
// the output is:
// minimal difference between longest and shortest edge: 1.8
// edges in the best solution:
// edge: 0 <- 0
// edge: 1 <- 1
// edge: 2 <- 2
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
using namespace std;
int i,j,n,m;
float edges[100][100];
vector<float> arr;
bool find_path(const set<pair<int, int> >& E, int a, int n, vector<int>& last, vector<bool>& checked) {
for(int i = 0; i < n; ++i) {
if(!checked[i] && E.count(make_pair(a, i))) {
checked[i]=true;
int temp = last[i];
last[i]=a;
if (temp < 0 || find_path(E, temp, n, last, checked)) {
return true;
}
last[i]=temp;
}
}
return false;
}
set<pair<int, int> >& Simple_Hungarian(const set<pair<int, int> >& E, int n) {
static set<pair<int, int> > ans;
static vector<int> last;
static vector<bool> checked;
ans.clear();
last.resize(n);
fill(last.begin(), last.end(), -1);
checked.resize(n);
for(int i = 0; i < n; ++i) {
fill(checked.begin(), checked.end(), false);
find_path(E, i, n, last, checked);
}
for(int i = 0; i < n; ++i) {
if (last[i] >=0)
ans.insert(make_pair(last[i], i));
}
return ans;
}
int main() {
cin >> n;
for(i=0;i<n;i++) {
for(j=0;j<n;j++) {
cin >> edges[i][j];
arr.push_back(edges[i][j]);
}
}
sort(arr.begin(), arr.end());
arr.resize(distance(arr.begin(), unique(arr.begin(), arr.end())));
set<pair<int, int> > ans;
float ans_diff=-1;
for(int low_i = 0; low_i < (int)arr.size(); ++low_i) {
float low = arr[low_i];
int high_l = i, high_r = arr.size()-1, mid;
while(high_l <= high_r) {
mid = (high_l+high_r)/2;
float high = arr[mid];
set<pair<int, int> > filtered_edges;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if(edges[i][j] >= low && edges[i][j] <= high) {
filtered_edges.insert(make_pair(i,j));
}
}
}
const set<pair<int, int> >& max_match = Simple_Hungarian(filtered_edges, n);
if ((int)max_match.size() == n) {
high_r = mid-1;
} else {
high_l = mid+1;
}
}
float high = arr[high_l];
if (high_l < (int) arr.size() && high_l >= low_i && (ans_diff < 0 || high-low < ans_diff)) {
ans_diff = high - low;
set<pair<int, int> > filtered_edges;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if(edges[i][j] >= low && edges[i][j] <= high) {
filtered_edges.insert(make_pair(i,j));
}
}
}
ans = Simple_Hungarian(filtered_edges, n);
}
}
cout << "minimal difference between longest and shortest edge: " << ans_diff << endl;
cout << "edges in the best solution: " << endl;
for(i=0;i<n;i++) {
for(j=0;j<n;j++) {
if (ans.count(make_pair(i, j))) {
cout << "edge: " << i << " <- " << j << endl;
}
}
}
return 0;
}
Ly8gZm9yIGlucHV0OiAKLy8gMwovLyAxMC43IDggMTguOSAKLy8gNi42IDExLjIgMTMuNyAKLy8gMTQuMSAxMy44IDkuNAovLyAKLy8gdGhlIG91dHB1dCBpczoKLy8gbWluaW1hbCBkaWZmZXJlbmNlIGJldHdlZW4gbG9uZ2VzdCBhbmQgc2hvcnRlc3QgZWRnZTogMS44Ci8vIGVkZ2VzIGluIHRoZSBiZXN0IHNvbHV0aW9uOiAKLy8gZWRnZTogMCA8LSAwCi8vIGVkZ2U6IDEgPC0gMQovLyBlZGdlOiAyIDwtIDIKI2luY2x1ZGU8aW9zdHJlYW0+CiNpbmNsdWRlPGFsZ29yaXRobT4KI2luY2x1ZGU8dmVjdG9yPgojaW5jbHVkZTxzZXQ+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgppbnQgaSxqLG4sbTsKCmZsb2F0IGVkZ2VzWzEwMF1bMTAwXTsKCnZlY3RvcjxmbG9hdD4gYXJyOwoKYm9vbCBmaW5kX3BhdGgoY29uc3Qgc2V0PHBhaXI8aW50LCBpbnQ+ID4mIEUsIGludCBhLCBpbnQgbiwgdmVjdG9yPGludD4mIGxhc3QsIHZlY3Rvcjxib29sPiYgY2hlY2tlZCkgewogIGZvcihpbnQgaSA9IDA7IGkgPCBuOyArK2kpIHsKICAgIGlmKCFjaGVja2VkW2ldICYmIEUuY291bnQobWFrZV9wYWlyKGEsIGkpKSkgewogICAgICBjaGVja2VkW2ldPXRydWU7CiAgICAgIGludCB0ZW1wID0gbGFzdFtpXTsKICAgICAgbGFzdFtpXT1hOwogICAgICBpZiAodGVtcCA8IDAgfHwgZmluZF9wYXRoKEUsIHRlbXAsIG4sIGxhc3QsIGNoZWNrZWQpKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgbGFzdFtpXT10ZW1wOwogICAgfQogIH0KICByZXR1cm4gZmFsc2U7Cn0KCnNldDxwYWlyPGludCwgaW50PiA+JiBTaW1wbGVfSHVuZ2FyaWFuKGNvbnN0IHNldDxwYWlyPGludCwgaW50PiA+JiBFLCBpbnQgbikgewogIHN0YXRpYyBzZXQ8cGFpcjxpbnQsIGludD4gPiBhbnM7CiAgc3RhdGljIHZlY3RvcjxpbnQ+IGxhc3Q7CiAgc3RhdGljIHZlY3Rvcjxib29sPiBjaGVja2VkOwogIGFucy5jbGVhcigpOwogIGxhc3QucmVzaXplKG4pOwogIGZpbGwobGFzdC5iZWdpbigpLCBsYXN0LmVuZCgpLCAtMSk7CiAgY2hlY2tlZC5yZXNpemUobik7CiAgZm9yKGludCBpID0gMDsgaSA8IG47ICsraSkgewogICAgZmlsbChjaGVja2VkLmJlZ2luKCksIGNoZWNrZWQuZW5kKCksIGZhbHNlKTsKICAgIGZpbmRfcGF0aChFLCBpLCBuLCBsYXN0LCBjaGVja2VkKTsKICB9CgogIGZvcihpbnQgaSA9IDA7IGkgPCBuOyArK2kpIHsKICAgIGlmIChsYXN0W2ldID49MCkgCiAgICAgIGFucy5pbnNlcnQobWFrZV9wYWlyKGxhc3RbaV0sIGkpKTsKICB9CiAgcmV0dXJuIGFuczsKfQoKaW50IG1haW4oKSB7CiAgY2luID4+IG47CiAgZm9yKGk9MDtpPG47aSsrKSB7CiAgICBmb3Ioaj0wO2o8bjtqKyspIHsKICAgICAgY2luID4+IGVkZ2VzW2ldW2pdOwogICAgICBhcnIucHVzaF9iYWNrKGVkZ2VzW2ldW2pdKTsKICAgIH0KICB9CiAgc29ydChhcnIuYmVnaW4oKSwgYXJyLmVuZCgpKTsKICBhcnIucmVzaXplKGRpc3RhbmNlKGFyci5iZWdpbigpLCB1bmlxdWUoYXJyLmJlZ2luKCksIGFyci5lbmQoKSkpKTsKICBzZXQ8cGFpcjxpbnQsIGludD4gPiBhbnM7CiAgZmxvYXQgYW5zX2RpZmY9LTE7CiAgZm9yKGludCBsb3dfaSA9IDA7IGxvd19pIDwgKGludClhcnIuc2l6ZSgpOyArK2xvd19pKSB7CiAgICBmbG9hdCBsb3cgPSBhcnJbbG93X2ldOwogICAgaW50IGhpZ2hfbCA9IGksIGhpZ2hfciA9IGFyci5zaXplKCktMSwgbWlkOwogICAgd2hpbGUoaGlnaF9sIDw9IGhpZ2hfcikgewogICAgICBtaWQgPSAoaGlnaF9sK2hpZ2hfcikvMjsKICAgICAgZmxvYXQgaGlnaCA9IGFyclttaWRdOwogICAgICBzZXQ8cGFpcjxpbnQsIGludD4gPiBmaWx0ZXJlZF9lZGdlczsKICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspIHsKICAgICAgICBmb3IgKGludCBqID0gMDsgaiA8IG47IGorKykgewogICAgICAgICAgaWYoZWRnZXNbaV1bal0gPj0gbG93ICYmIGVkZ2VzW2ldW2pdIDw9IGhpZ2gpIHsKICAgICAgICAgICAgZmlsdGVyZWRfZWRnZXMuaW5zZXJ0KG1ha2VfcGFpcihpLGopKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgY29uc3Qgc2V0PHBhaXI8aW50LCBpbnQ+ID4mIG1heF9tYXRjaCA9IFNpbXBsZV9IdW5nYXJpYW4oZmlsdGVyZWRfZWRnZXMsIG4pOwogICAgICAKICAgICAgaWYgKChpbnQpbWF4X21hdGNoLnNpemUoKSA9PSBuKSB7CiAgICAgICAgaGlnaF9yID0gbWlkLTE7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgaGlnaF9sID0gbWlkKzE7CiAgICAgIH0KICAgIH0KICAgIGZsb2F0IGhpZ2ggPSBhcnJbaGlnaF9sXTsKICAgIGlmIChoaWdoX2wgPCAoaW50KSBhcnIuc2l6ZSgpICYmIGhpZ2hfbCA+PSBsb3dfaSAmJiAoYW5zX2RpZmYgPCAwIHx8IGhpZ2gtbG93IDwgYW5zX2RpZmYpKSB7CiAgICAgIGFuc19kaWZmID0gaGlnaCAtIGxvdzsKICAgICAgc2V0PHBhaXI8aW50LCBpbnQ+ID4gZmlsdGVyZWRfZWRnZXM7CiAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbjsgaSsrKSB7CiAgICAgICAgZm9yIChpbnQgaiA9IDA7IGogPCBuOyBqKyspIHsKICAgICAgICAgIGlmKGVkZ2VzW2ldW2pdID49IGxvdyAmJiBlZGdlc1tpXVtqXSA8PSBoaWdoKSB7CiAgICAgICAgICAgIGZpbHRlcmVkX2VkZ2VzLmluc2VydChtYWtlX3BhaXIoaSxqKSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICAgIGFucyA9IFNpbXBsZV9IdW5nYXJpYW4oZmlsdGVyZWRfZWRnZXMsIG4pOwogICAgfQogIH0KICBjb3V0IDw8ICJtaW5pbWFsIGRpZmZlcmVuY2UgYmV0d2VlbiBsb25nZXN0IGFuZCBzaG9ydGVzdCBlZGdlOiAiIDw8IGFuc19kaWZmIDw8IGVuZGw7CgogIGNvdXQgPDwgImVkZ2VzIGluIHRoZSBiZXN0IHNvbHV0aW9uOiAiIDw8IGVuZGw7CiAgZm9yKGk9MDtpPG47aSsrKSB7CiAgICBmb3Ioaj0wO2o8bjtqKyspIHsKICAgICAgaWYgKGFucy5jb3VudChtYWtlX3BhaXIoaSwgaikpKSB7CiAgICAgICAgY291dCA8PCAiZWRnZTogIiA8PCBpIDw8ICIgPC0gIiA8PCBqIDw8IGVuZGw7CiAgICAgIH0KICAgIH0KICB9CgogIHJldHVybiAwOwp9Cg==