#include "towns.h"
#include <bits/stdc++.h>
using namespace std;
#define forn(i,n) for(int i=0;i<n;++i)
#define pb push_back
#define all(x) x.begin(), x.end()
#define pi pair<int,int>
#define f first
#define s second
const int inf=1e9+9;
const int _N=555;
int d[_N][_N];
struct DSU {
vector<int> p,sz;
DSU(int n) {forn(i,n)p.pb(i),sz.pb(1);}
int get(int u) {return p[u]==u?u:get(p[u]);}
void uni(int u, int v){
u=get(u),v=get(v); if (u==v)return; if (sz[u]<sz[v]) swap(u,v);
p[v]=u;sz[u]+=sz[v];
}
};
int p3(int n) {
forn(i,n) {
forn(j,i) {
int x=getDistance(i,j);
d[i][j]=d[j][i]=x;
}
}
int f=0,s=0;
forn(i,n) if (d[0][i]>d[0][f]) f=i;
forn(i,n) if (d[f][i]>d[f][s]) s=i;
int ans=inf;
map<int,int> cnt;
map<int,vector<int>> q;
vector<int> ok(n);
set<int> s1,s2;
forn(i,n) {
if (i==f || i==s) continue;
int x=d[f][i], y=d[s][i], z=d[f][s];
int A=(x-y+z)/2;
int B=z-A;
int C=x-A;
ans=min(ans,max(A,B));
ok[i]=C;
cnt[A]++;
q[A].pb(i);
s1.insert(A), s2.insert(B);
}
int left=1;
vector<int> x,y;
for(auto&t:s1)x.pb(t);
for(auto&t:s2)y.pb(t);
reverse(all(y));
forn(i,s1.size()) {
if (max(x[i],y[i])==ans) {
int right=n-left-cnt[x[i]];
int mx=max(left,right);
DSU dsu(n);
for(auto&u:q[x[i]]) {
for(auto&v:q[x[i]]) {
int dist = d[u][v];
if (dist < ok[u]+ok[v]) dsu.uni(u,v);
}
}
forn(j,n) mx=max(mx,dsu.sz[j]);
if (mx<=n/2) return ans;
}
left+=cnt[x[i]];
}
return -ans;
}
int p5(int n) {
vector<int> a(n), b(n), c(n);
int f=0;
forn(i,n) {
a[i]=getDistance(0,i);
if (a[i]>a[f]) f=i;
}
int s=0;
forn(i,n) {
b[i]=getDistance(f,i);
if (b[i]>b[s]) s=i;
}
forn(i,n) {
c[i]=getDistance(s,i);
}
set<int> st;
vector<int> d(n);
map<int,vector<int>> ok;
forn(i,n) {
if (i==f || i==s) continue;
int x=b[i], y=c[i], z=b[s];
int A=(x-y+z)/2;
d[i]=x-A;
st.insert(A);
ok[A].pb(i);
}
int ans=inf;
for(auto&x:st) {
int y=b[s]-x;
ans=min(ans,max(x,y));
}
int l=1;
for(auto&x:st) {
int y=b[s]-x;
if (max(x,y)!=ans) {
l+=ok[x].size();
continue;
}
int r=n-ok[x].size()-l;
if (max(l,r)>n/2) continue;
int t=ok[x].size();
if (t<=n/2) return ans;
vector<pi> a,b;
for(auto&v:ok[x]) a.pb({v,1});
while (a.size()>1) {
int k = a.size();
for (int i=0; i+1<a.size(); i+=2) {
int z = getDistance(a[i].f,a[i+1].f);
int x = d[a[i].f], y = d[a[i+1].f];
if (z==x+y) {
if (a[i].s > a[i+1].s) b.pb(a[i]);
else b.pb(a[i+1]);
continue;
}
b.pb({a[i].f,a[i].s+a[i+1].s});
}
if (k&1) b.pb(a.back());
a=b;
b.clear();
}
int u=a[0].f;
int sz=0;
for(auto&v:ok[x]) {
int z = getDistance(u,v);
int x = c[u], y = c[v];
if (z<x+y) ++sz;
}
if (sz<=n/2) return ans;
}
return -ans;
}
int hubDistance(int n, int sub) {
if (sub<=2 || sub>=4) return p5(n);
if (sub==3) return p3(n);
return 0;
}