using ld = long double;
using pdd = pair<ld, ld>;
using line = pair<pdd, pdd>; // half plane : left side of vector fi->se

const ld eps = 1e-9;
pdd operator*(const pdd& a, ld s) { return {a.fi * s, a.se * s}; }
inline bool equals(ld a, ld b) { return abs(a - b) < eps; }

bool line_intersect(line& a, line& b, pdd& v) {
    ld det = (a.se - a.fi) / (b.se - b.fi);
    if (equals(det, 0)) return 0;
    ld t = ((b.fi - a.fi) / (b.se - b.fi)) / det; 
    v = a.fi + (a.se - a.fi) * t;
    return 1;
}

bool bad(line& a, line& b, line& c) {
    pdd v; if(!line_intersect(a, b, v)) return 0;
    return (c.se - c.fi) / (v - c.fi) <= eps;
}

vector<pdd> HPI(vector<line>& lns) {
    auto lsgn = [&](const line& a) {
        if(a.fi.se == a.se.se) return a.fi.fi > a.se.fi;
        return a.fi.se > a.se.se;
    };
    sort(lns.begin(), lns.end(), [&](const line& a, const line& b) {
        if(lsgn(a) != lsgn(b)) return lsgn(a) < lsgn(b);
        return (a.se - a.fi) / (b.se - b.fi) > 0;
    });
    
    deque<line> dq;
    for(auto l : lns){
        while(dq.size() >= 2 && bad(dq[dq.size()-2], dq.back(), l)) dq.pop_back();
        while(dq.size() >= 2 && bad(dq[0], dq[1], l)) dq.pop_front();
        
        if(dq.size() < 2 || !bad(dq.back(), l, dq[0])) dq.pb(l);
    }
    
    vector<pdd> res;
    if(dq.size() >= 3) {
        for(int i = 0; i < (int)dq.size(); i++) {
            int j = (i + 1) % (int)dq.size();
            pdd v;
            if(!line_intersect(dq[i], dq[j], v)) continue;
            res.push_back(v);
        }
    }
    return res;
}