#include #pragma GCC optimize("O3") //#define int long long using namespace std; int fnd(int x, vector &p){ if(p[x] < 0) return x; return p[x] = fnd(p[x],p); } void mrg(int x, int y, vector &p, int out){ x = fnd(x,p), y = fnd(y,p); if(x == y){ cout << out << "\n"; exit(0); } if(p[x] > p[y]) swap(x,y); p[x] += p[y]; p[y] = x; } signed main(){ cin.tie(0); ios::sync_with_stdio(0); int m; cin >> m; map,int> pti; // point to index set> edges; int sol = 3; vector> points; vector ch, cv; // connected horizontally, vertically vector> e; for(int i = 0; i < m; i++){ int x, y, X, Y; cin >> x >> y >> X >> Y; if(!pti.count({x,y})){ pti[{x,y}] = points.size(), points.push_back({x,y}); cv.push_back(0), ch.push_back(0); } if(!pti.count({X,Y})){ pti[{X,Y}] = points.size(), points.push_back({X,Y}); cv.push_back(0), ch.push_back(0); } edges.insert({x,y,X,Y}); edges.insert({X,Y,x,y}); e.push_back({pti[{x,y}],pti[{X,Y}]}); if(x != X){ ch[pti[{x,y}]] = 1; ch[pti[{X,Y}]] = 1; if(edges.count({x,y-1,X,Y-1}) || edges.count({x,y+1,X,Y+1})){ sol = 2; } } else{ cv[pti[{x,y}]] = 1; cv[pti[{X,Y}]] = 1; if(edges.count({x-1,y,X-1,Y}) || edges.count({x+1,y,X+1,Y})){ sol = 2; } } } int n = points.size(); for(int i = 0; i < n; i++){ if(cv[i] && ch[i]) sol = 2; } vector p(n,-1); for(auto t : e){ int a,b; tie(a,b) = t; mrg(a,b,p,0); } for(int i = 0; i < n; i++){ int x,y; tie(x,y) = points[i]; pair dir[] = {{0,1},{1,0},{0,-1},{-1,0}}; for(int k = 0; k < 4; k++){ int X = x+dir[k].first, Y = y+dir[k].second; if(!pti.count({X,Y})) continue; if(edges.count({x,y,X,Y})) continue; if(fnd(i, p) == fnd(pti[{X,Y}],p)){ cout << "1\n"; exit(0); } } } cout << sol << "\n"; }