#include using namespace std; using ll = long long; using vll = vector; using pll = pair; #define sz(x) ((ll)(x).size()) #define For(i, a, n) for(ll i = a; i < (ll)(n); i++) #define xx first #define yy second const ll MOD = 1e9+7; template ostream& operator<<(ostream &os, const vector &cont) { for (auto it = cont.begin(); it != cont.end(); ++it) os << (it == cont.begin() ? "" : " ") << *it; return os; } template ostream& operator<<(ostream &os, const pair &cont) { os << "(" << cont.first << ", " << cont.second << ")"; return os; } using point = pll; using line = pair; struct UF { vll parent; UF(ll n) : parent(n, -1) {} ll find(ll x) { if (parent[x] < 0) return x; return parent[x] = find(parent[x]); } bool join(ll x, ll y, bool dry=false) { x = find(x); y = find(y); if (x == y) return false; if (dry) return true; if (parent[x] > parent[y]) swap(x, y); parent[x] += parent[y]; parent[y] = x; return true; } }; point operator+(const point p1, const point p2) { return {p1.first + p2.first, p1.second + p2.second}; } line canonize(line l) { if (l.first.xx > l.second.xx || l.first.yy > l.second.yy) swap(l.first, l.second); return l; } bool is_vertical(line &l) { return l.first.xx == l.second.xx; } line add(line l, point d) { return {l.first + d, l.second + d}; } void add_point(map &points, point p) { if (!points.count(p)) { int s = sz(points); points[p] = s; } } int main() { ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); ll N; cin >> N; map points; set lines; For(i, 0, N) { ll x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2; point p1{x1, y1}, p2{x2, y2}; tie(p1, p2) = canonize(line(p1, p2)); add_point(points, p1); add_point(points, p2); lines.insert({p1, p2}); } if (N == 0) { cout << 4 << endl; return 0; } ll res = 3; for (auto line1: lines) { point p1, p2; tie(p1, p2) = line1; if (is_vertical(line1)) { line line2 = add(line1, point(-1, 0)); if (lines.count(line2)) res = 2; line2 = add(line1, point(1, 0)); if (lines.count(line2)) res = 2; } else { line line2 = add(line1, point(0, -1)); if (lines.count(line2)) res = 2; line2 = add(line1, point(0, 1)); if (lines.count(line2)) res = 2; } } vector dirs = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; for (auto [center, ucenter]: points) { For(di, 0, 4) { point d1 = dirs[di]; point d2 = dirs[(di + 1) % 4]; line l1 = canonize(line(center, center + d1)); line l2 = canonize(line(center, center + d2)); if (lines.count(l1) && lines.count(l2)) res = 2; } } if (res == 3) { cout << res << endl; return 0; } UF uf(sz(points)); for (auto line: lines) { ll u1 = points[line.first]; ll u2 = points[line.second]; if (!uf.join(u1, u2)) { cout << 0 << endl; return 0; } } for (auto [point1, u1]: points) { for (auto dir: dirs) { point point2 = point1 + dir; line l = canonize(line(point1, point2)); if (!points.count(point2) || lines.count(l)) continue; ll u2 = points[point2]; if (!uf.join(u1, u2, true)) { cout << 1 << endl; return 0; } } } cout << 2 << endl; }