#!/usr/bin/env python3

import sys
import math, cmath
from collections import defaultdict

M = sys.stdin.readline()
for x in M.rstrip("\n"):
    assert x in "1234567890", f"M = '{x}' (first line) should be integer"
assert M[0] != "0"
M = int(M)
assert 3 <= M <= 1000, f"Number of edges should be 3 <= {M} <= 1000"
lines = []
for l in sys.stdin:
    for c in l.rstrip("\n"):
        assert c in " 1234567890"
    edge = tuple(int(i) for i in l.split())
    assert len(edge) == 4
    assert (edge[0], edge[1]) != (edge[2], edge[3]), f"self loop {edge}"
    for x in edge:
        assert 0 <= x <= 1000, f"0 <= {x} <= 1000 broken!"
    lines.append(edge)
assert len(lines) == M


class Vec:
    def __init__(self, x=None, y=None, c=None):
        if c is None:
            if x is None or y is None:
                raise ValueError("Either (x or y) or c")
            self.c = complex(x, y)
        else:
            if x is not None or y is not None:
                raise ValueError("When c, not x y")
            self.c = c

    @property
    def x(self):
        return self.c.real

    @property
    def y(self):
        return self.c.imag

    def __mul__(self, o):
        if isinstance(o, Vec):
            o = o.c
        return Vec(c=self.c * o)

    def __truediv__(self, s):
        return Vec(self.x / s, self.y / s)

    def __add__(self, o):
        if isinstance(o, Vec):
            o = o.c
        return Vec(c=self.c + o)

    def __sub__(self, o):
        if isinstance(o, Vec):
            o = o.c
        return Vec(c=self.c - o)

    @property
    def conj(self):
        return Vec(c=self.c.conjugate())

    def is_perp(v1, v2):
        return dot(v1, v2) == 0

    def cross(v1, v2):
        return (v1.conj * v2).y  # y

    def __hash__(v):
        return hash(v.c)

    def __eq__(v1, v2):
        return v1.c == v2.c

    def __lt__(v1, v2):
        return (v1.x, v1.y) <= (v2.x, v2.y)

    def __repr__(v):
        return f"({v.x}, {v.y})"


def dot(v1, v2):
        return v1.x * v2.x + v1.y * v2.y


def orient(a, b, c):
    return (b - a).cross(c - a)


def endpoints(l):
    return Vec(l[0], l[1]), Vec(l[2], l[3])


def sgn2(k, l):
    """k and l have different sign"""
    return k * l < 0


def intersect(line1, line2):
    (a, b), (c, d) = line1, line2
    oa = orient(c, d, a)
    ob = orient(c, d, b)
    oc = orient(a, b, c)
    od = orient(a, b, d)
    if sgn2(oa, ob) and sgn2(oc, od):
        return (a * ob - b * oa) / (ob - oa)


for i, l1 in enumerate(lines):
    for l2 in lines[i + 1 :]:
        p1, p2 = endpoints(l1)
        q1, q2 = endpoints(l2)
        assert not intersect((p1, p2), (q1, q2))

V = []
N = defaultdict(list)
for line in lines:
    p1, p2 = endpoints(line)
    V += [p1, p2]
    N[p1].append(p2)
    N[p2].append(p1)

V = sorted(set(V))


def dfs(v, N, visited):
    visited.add(v)
    for neighbor in N[v]:
        if neighbor not in visited:
            dfs(neighbor, N, visited)


def is_connected(V, N):
    visited = set()
    dfs(V[0], N, visited)
    return len(visited) == len(V)


# Check connected:

assert is_connected(V, N), "Graph is disconnected"


# Check 2-connected:

for line in lines:
    p1, p2 = endpoints(line)
    N[p1].remove(p2)
    N[p2].remove(p1)
    assert is_connected(V, N), f"G not two-connected on edge {p1}, {p2}"
    N[p1].append(p2)
    N[p2].append(p1)

sys.exit(42)
