Problem:
Problem E:
Geometric Map
Your task in this problem is to create a program that finds the shortest path between two given
locations on a given street map, which is represented as a collection of line segments on a plane.
Figure 4 is an example of a street map, where some line segments represent streets and the
others are signs indicating the directions in which cars cannot move. More concretely,
AE
,
AM
,
MQ
,
EQ
,
CP
and
HJ
represent the streets and the others are signs in this map. In general, an end point of a sign touches one and only one line segment representing a street and the other end point is open. Each end point of every street touches one or more streets, but no signs.
The sign
BF
, for instance, indicates that at
B
cars may move left to right but may not in the
reverse direction. In general, cars may not move from the obtuse angle side to the acute angle
side at a point where a sign touches a street (note that the angle
CBF
is obtuse and the angle
ABF
is acute). Cars may directly move neither from
P
to
M
nor from
M
to
P
since cars moving left
to right may not go through
N
and those moving right to left may not go through
O
. In a special
case where the angle between a sign and a street is rectangular, cars may not move in either
directions at the point. For instance, cars may directly move neither from
H
to
J
nor from
J
to
H
.
You should write a program that finds the shortest path obeying these traffic rules. The length of a line segment between (
x
1
,
y
1
) and (
x
2
,
y
2
) is √{(
x
2
−
x
1
)
2
+ (
y
2
−
y
1
)
2
} .
Input
The input consists of multiple datasets, each in the following format.
n
x
s
y
s
x
g
y
g
x
1
1
y
1
1
x
2
1
y
2
1
.
  .
  .
x
1
k
y
1
k
x
2
k
y
2
k
.
  .
  .
x
1
n
y
1
n
x
2
n
y
2
n
n
, representing the number of line segments, is a positive integer less than or equal to 200.
(
x
s
,
y
s
) and (
x
g
,
y
g
) are the start and goal points, respectively. You can assume that (
x
s
,
y
s
) ≠ (
x
g
,
y
g
) and that each of them is located on an end point of some line segment representing a street. You can also assume that the shortest path from (
x
s
,
y
s
) to (
x
g
,
y
g
) is unique.
(
x
1
k
,
y
1
k
) and (
x
2
k
,
y
2
k
) are the two end points of the kth line segment. You can assume that 
(
x
1
k
,
y
1
k
) ≠(
x
2
k
,
y
2
k
).
Two line segments never cross nor overlap. That is, if they share a point, it is always one of their end points.
All the coordinates are non-negative integers less than or equal to 1000. The end of the input is indicated by a line containing a single zero.
Output
For each input dataset, print every street intersection point on the shortest path from the start
point to the goal point, one in an output line in this order, and a zero in a line following
those points. Note that a street intersection point is a point where at least two line segments
representing streets meet. An output line for a street intersection point should contain its
x
- and
y
-coordinates separated by a space.
Print
-1
if t
...(truncated)

Submitted solutions:

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
const ll mod = 998244353;
const ll INF = (1e+18) + 7;
typedef pair<int, int>P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-6;
const ld pi = acos(-1.0);
//typedef vector<vector<ll>> mat;
typedef vector<int> vec;

ll mod_pow(ll a, ll n) {
	ll res = 1;
	while (n) {
		if (n & 1)res = res * a%mod;
		a = a * a%mod; n >>= 1;
	}
	return res;
}

struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n%mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint &a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint &a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint &a, modint b) { a.n = ((ll)a.n*b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, int n) {
	if (n == 0)return modint(1);
	modint res = (a*a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p%a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }

const int max_n = 500;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}

int dx[4] = { 0,1,0,-1 };
int dy[4] = { 1,0,-1,0 };


using speP = pair<ld, int>;

struct edge {
	int to; ld cost;
};
ld dist(P a, P b) {
	ld dx = b.first - a.first;
	ld dy = b.second - a.second;
	return sqrt(pow(dx, 2) + pow(dy, 2));
}

bool ison(P a, P l, P r) {
	ld cl = dist(a, l);
	ld cr = dist(a, r);
	ld cm = dist(l, r);
	return abs(cl + cr - cm) < eps;
}

int ban(P a, P b, P l, P r) {
	if (!ison(l, a, b))swap(l, r);
	int dx1 = b.first - a.first;
	int dy1 = b.second - a.second;
	int dx2 = r.first - l.first;
	int dy2 = r.second - l.second;
	int z = dx1 * dx2 + dy1 * dy2;
	if (z == 0)return 3;
	if (z > 0)return 1;
	if (z < 0)return 2;
}
int n;
void solve() {
	int cx[2], cy[2];
	rep(i, 2)cin >> cx[i] >> cy[i];
	vector<P> lep(n), rip(n);
	rep(i, n) {
		int x, y; cin >> x >> y;
		lep[i] = { x,y };
		cin >> x >> y;
		rip[i] = { x,y };
	}
	vector<bool> ism(n, false);
	rep(i, n) {
		P p = lep[i];
		int tmp = 0;
		rep(j, n) {
			if (i == j)continue;
			if (ison(p, lep[j], rip[j])) {
				tmp++; break;
			}
		}
		p = rip[i];
		rep(j, n) {
			if (i == j)continue;
			if (ison(p, lep[j], rip[j])) {
				tmp++; break;
			}
		}
		ism[i] = (tmp == 2);
		/*cout << i << " ! " << tmp << endl;
		if (ism[i]) {
			cout << "!! " << i << endl;
		}*/
	}
	vector<P> ps;
	rep(i, n) {
		if (!ism[i])continue;
		rep(j, n) {
			if (i == j)continue;
			if (!ism[j])continue;
			if (ison(lep[i], lep[j], rip[j])) {
				ps.push_back(lep[i]);
			}
			if (ison(rip[i], lep[j], rip[j])) {
				ps.push_back(rip[i]);
			}
		}
	}
	sort(all(ps));
	ps.erase(unique(all(ps)), ps.end());
	//cout << "! " << ps.size() << endl;
	//rep(i, ps.size())cout << ps[i].first << " " << ps[i].second << endl;
	vector<vector<pair<P, int>>> onp(n);
	rep(i, n) {
		rep(j, n) {
			if (i == j)continue;
			if (!ism[j])continue;
			int id = -1;
			if (!ism[i])id = i;
			if (ison(lep[i], lep[j], rip[j])) {
				onp[j].push_back({ lep[i],id });
			}
			if (ison(rip[i], lep[j], rip[j])) {
				onp[j].push_back({ rip[i],id });
			}
		}
	}
	rep(i, n) {
		onp[i].push_back({ lep[i],-1 });
		onp[i].push_back({ rip[i],-1 });
		sort(all(onp[i]));
		onp[i].erase(unique(all(onp[i])), onp[i].end());
	}
	map<P, int> mp;
	rep(i, ps.size())mp[ps[i]] = i;

	vector<vector<edge>> G(ps.size());
	rep(i, n) {
		if (!ism[i])continue;
		vector<int> ids;
		//cout << "???? " << i << endl;
		rep(j, onp[i].size()) {
			if (onp[i][j].second < 0) {
				ids.push_back(j);
				//cout << onp[i][j].first.first << " " << onp[i][j].first.second << endl;
			}
		}
		rep(j, (int)ids.size() - 1) {
			int leid = ids[j];
			int riid = ids[j + 1];
			bool fle = true, fri = true;
			for (int x = leid + 1; x <= riid - 1; x++) {
				int id = onp[i][x].second;
				int t = ban(onp[i][leid].first, onp[i][riid].first, lep[id], rip[id]);
				if (t & 1)fle = false;
				if (t & 2)fri = false;
			}
			int l = mp[onp[i][leid].first];
			int r = mp[onp[i][riid].first];
			if (fle) {
				//cout << l << " " << r << endl;
				G[l].push_back({ r,dist(ps[l],ps[r]) });
			}
			if (fri) {
				//cout << r << " " << l << endl;
				G[r].push_back({ l,dist(ps[r],ps[l]) });
			}
		}
	}
	vector<ld> dist(ps.size(),INF);
	vector<int> pre(ps.size(), -1);
	int sta = mp[{cx[0], cy[0]}];
	int goa = mp[{cx[1], cy[1]}];
	priority_queue<speP, vector<speP>, greater<speP>> q;
	dist[sta] = 0; q.push({ 0,sta });
	while (!q.empty()) {
		speP p = q.top(); q.pop();
		int id = p.second;
		if (dist[id] < p.first)continue;
		for (edge e : G[id]) {
			ld nd = dist[id] + e.cost;
			if (nd < dist[e.to]) {
				dist[e.to] = nd;
				pre[e.to] = id;
				q.push({ nd,e.to });
			}
		}
	}
	if (dist[goa] == INF) {
		cout << -1 << endl; return;
	}
	vector<P> memo;
	int cur = goa;
	while (cur != sta) {
		memo.push_back(ps[cur]);
		cur = pre[cur];
	}
	memo.push_back(ps[sta]);
	reverse(all(memo));
	rep(i, memo.size()) {
		cout << memo[i].first << " " << memo[i].second << endl;
	}
	cout << 0 << endl;
}


signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(10);
	//init_f(); init();
	//int t; cin >> t; rep(i, t)solve();
	while (cin >> n, n)solve();
	stop
		return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3292
final_rank: 8

code_snippet: #include <bits/stdc++.h>
#define rep(i,n) for (int i = 0; i < n; i++)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pi;
typedef pair<pi, pi> pp;
typedef pair<double, pi> pdp;
typedef pair<ll, ll> pl;
const double EPS = 1e-9;
const ll mod = 1000000007;
const int inf = 1 << 30;
const ll linf = 1LL << 60;
const double PI = 3.14159265358979323846;

typedef double D;
typedef complex<D> P;
typedef pair<P, P> L;
typedef vector<P> VP;
#define X real()
#define Y imag()
#define LE(n,m) ((n) < (m) + EPS)
#define GE(n,m) ((n) + EPS > (m))
#define EQ(n,m) (abs((n)-(m)) < EPS)

D dot(P a, P b) {
    return (conj(a)*b).X;
}

D cross(P a, P b) {
    return (conj(a)*b).Y;
}

int ccw(P a, P b, P c) {
    b -= a; c -= a;
    if (cross(b,c) >  EPS) return +1;
    if (cross(b,c) < -EPS) return -1;
    if (dot(b,c)   < -EPS) return +2;
    if (norm(b) < norm(c)) return -2;
    return 0;
}

bool isecSP(P a1, P a2, P b) {
    return !ccw(a1, a2, b);
}

int n;
pi star, goal;
map<pi, int> m;
map<pi, vector<pdp>> edges;
map<pi, double> dp;
map<pi, pi> rev;
pp lines[200];

void solve() {
    m.clear();
    edges.clear();
    cin >> star.first >> star.second >> goal.first >> goal.second;
    rep(i,n) {
        cin >> lines[i].first.first >> lines[i].first.second >> lines[i].second.first >> lines[i].second.second;
    }
    rep(i,n) {
        rep(j,n) {
            P p1 = P(lines[i].first.first, lines[i].first.second);
            P p2 = P(lines[i].second.first, lines[i].second.second);
            P p3 = P(lines[j].first.first, lines[j].first.second);
            P p4 = P(lines[j].second.first, lines[j].second.second);
            if (isecSP(p3, p4, p1)) {
                m[lines[i].first]++;
            }
            if (isecSP(p3, p4, p2)) {
                m[lines[i].second]++;
            }
        }
    }
    rep(i,n) {
        P p1 = P(lines[i].first.first, lines[i].first.second);
        P p2 = P(lines[i].second.first, lines[i].second.second);
        if (m[lines[i].first] == 1 || m[lines[i].second] == 1) continue;
        vector<pdp> hoge;
        hoge.push_back(pdp(0.0, lines[i].first));
        hoge.push_back(pdp(abs(p1-p2), lines[i].second));

        rep(j,n) {
            if (i == j) continue;
            P p3 = P(lines[j].first.first, lines[j].first.second);
            P p4 = P(lines[j].second.first, lines[j].second.second);
            if (m[lines[j].first] == 1 || m[lines[j].second] == 1) continue;
            if (isecSP(p1, p2, p3) && !EQ(0.0, abs(p1-p3)) && !EQ(abs(p1-p2), abs(p1-p3))) {
                hoge.push_back(pdp(abs(p1-p3), lines[j].first));
            }
            if (isecSP(p1, p2, p4) && !EQ(0.0, abs(p1-p4)) && !EQ(abs(p1-p2), abs(p1-p4))) {
                hoge.push_back(pdp(abs(p1-p4), lines[j].second));
            }
        }
        sort(hoge.begin(), hoge.end());
        for (int j = 0; j < (int)hoge.size()-1; j++) {
            bool ok1 = true, ok2 = true;
            P p3 = P(hoge[j].second.first, hoge[j].second.second);
            P p4 = P(hoge[j+1].second.first, hoge[j+1].second.second);
            rep(k,n) {
                if (m[lines[k].first] != 1 && m[lines[k].second] != 1) continue;
                if (m[lines[k].first] == 1) swap(lines[k].first, lines[k].second);
                P p5 = P(lines[k].first.first, lines[k].first.second);
                P p6 = P(lines[k].second.first, lines[k].second.second);
                if (!isecSP(p3, p4, p5)) continue;
                if (GE(dot(p6-p5, p3-p5),0.0)) ok2 = false;
                if (LE(dot(p6-p5, p3-p5),0.0)) ok1 = false;
            }
            if (ok1) edges[hoge[j].second].push_back(pdp(hoge[j+1].first-hoge[j].first, hoge[j+1].second));
            if (ok2) edges[hoge[j+1].second].push_back(pdp(hoge[j+1].first-hoge[j].first, hoge[j].second));
        }
    }
    /*
    for (auto it = edges.begin(); it != edges.end(); it++) {
        cerr << endl;
        cerr << (*it).first.first << " " << (*it).first.second << endl;
        vector<pdp>& huga = (*it).second;
        for (pdp& piyo : huga) {
            cerr << piyo.second.first << " " << piyo.second.second << endl;
        }
    }
    */
    rep(i,n) {
        dp[lines[i].first] = inf;
        dp[lines[i].second] = inf;
    }
    dp[star] = 0.0;
    priority_queue<pdp, vector<pdp>, greater<pdp>> pque;
    pque.push(pdp(0.0, star));
    while (!pque.empty()) {
        pdp p = pque.top(); pque.pop();
        if (dp[p.second] < p.first) continue;
        for (auto& e : edges[p.second]) {
            if (dp[e.second] > p.first + e.first) {
                dp[e.second] = p.first + e.first;
                rev[e.second] = p.second;
                pque.push(pdp(dp[e.second], e.second));
            }
        }
    }
    if (dp[goal] > inf-1) {
        cout << -1 << endl;
        return;
    }
    vector<int> ans;
    pi pos = goal;
    while (true) {
        ans.push_back(pos.second); ans.push_back(pos.first);
        if (pos == star) break;
        pos = rev[pos];
    }
    for (int i = (int)ans.size()-1; i >= 0; i -= 2) {
        cout << ans[i] << " " << ans[i-1] << endl;
    }
    cout << 0 << endl;
}

int main() {
#ifndef LOCAL
    ios::sync_with_stdio(false);
    cin.tie(0);
#endif
    cout << fixed;
    cout.precision(20);
    cerr << fixed;
    cerr.precision(6);
#ifdef LOCAL
    //freopen("in.txt", "wt", stdout); //for tester
    freopen("in.txt", "rt", stdin);
#endif  
    while (cin >> n) {
        if (n == 0) break;
        solve();
    }
    //cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3192
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;

using pii = pair<int, int>;
using ld = long double;
using point = complex<ld>;

constexpr ld eps = 1e-8;
constexpr ld pi = acos(-1.0);

constexpr int inf = 1e9;

ld dist(pii const& p1, pii const& p2) {
    point a(p1.first, p1.second);
    point b(p2.first, p2.second);
    return abs(a - b);
}

struct segment {
    segment(pii a, pii b, int ai, int bi) : a(a), b(b), ai(ai), bi(bi) {}
    pii a, b;
    int ai, bi;
};

bool isis_sp(segment const& s, pii const& p) {
    return abs(dist(s.a, p) + dist(s.b, p) - dist(s.a, s.b)) < eps;
}

// segment is not cross, so this is ok
bool isis_ss(segment const& s1, segment const& s2) {
    return isis_sp(s1, s2.a) || isis_sp(s1, s2.b) || isis_sp(s2, s1.a) || isis_sp(s2, s1.b);
}

struct edge {
    int to, cost;
};

using edges = vector<edge>;
using graph = vector<edges>;

void add_edge(graph& g, int from, int to, int cost) {
    g[from].push_back({to, cost});
}

int main() {
    int n;
    while(cin >> n, n) {
        pii sp, gp;
        cin >> sp.first >> sp.second >> gp.first >> gp.second;
        vector<pii> ps = {sp, gp};
        vector<pii> p1(n), p2(n);
        for(int i = 0; i < n; ++i) {
            cin >> p1[i].first >> p1[i].second >> p2[i].first >> p2[i].second;
            ps.push_back(p1[i]);
            ps.push_back(p2[i]);
        }
        sort(begin(ps), end(ps));
        ps.erase(unique(begin(ps), end(ps)), end(ps));
        const int m = ps.size();

        auto get_idx = [&](pii p) {
            return lower_bound(begin(ps), end(ps), p) - begin(ps);
        };

        vector<segment> segs;
        for(int i = 0; i < n; ++i) {
            segs.emplace_back(p1[i], p2[i], get_idx(p1[i]), get_idx(p2[i]));
        }

        auto segment_arrangement = [&]() {
            vector<segment> res;
            for(int i = 0; i < n; ++i) {
                vector<pair<ld, int>> v;
                for(int j = 0; j < m; ++j) {
                    if(isis_sp(segs[i], ps[j])) {
                        v.emplace_back(dist(segs[i].a, ps[j]), j);
                    }
                }
                sort(begin(v), end(v));
                for(int j = 0; j + 1 < (int)v.size(); ++j) {
                    int p1 = v[j].second, p2 = v[j + 1].second;
                    res.emplace_back(ps[p1], ps[p2], p1, p2);
                }
            }
            return res;
        };
        segs = segment_arrangement();
        n = segs.size();

        vector<int> on_seg(m);
        for(int i = 0; i < m; ++i) {
            for(int j = 0; j < n; ++j) {
                on_seg[i] += isis_sp(segs[j], ps[i]);
            }
        }
        vector<bool> is_road(n); // is_mark is !is_road
        for(int i = 0; i < n; ++i) {
            is_road[i] = on_seg[segs[i].ai] > 1 && on_seg[segs[i].bi] > 1;
        }
        vector<int> is_intersection(m);
        vector<int> is_sign_intersection(m);
        for(int i = 0; i < m; ++i) {
            for(int j = 0; j < n; ++j) {
                if(is_road[j]) {
                    is_intersection[i] += isis_sp(segs[j], ps[i]);
                } else {
                    is_sign_intersection[i] |= isis_sp(segs[j], ps[i]);
                }
            }
        }
        for(int i = 0; i < m; ++i) {
            is_intersection[i] -= is_sign_intersection[i];
        }

        vector<vector<bool>> can_use(m, vector<bool>(m, false));
        for(int i = 0; i < n; ++i) {
            can_use[segs[i].ai][segs[i].bi] = true;
            can_use[segs[i].bi][segs[i].ai] = true;
        }
        for(int i = 0; i < n; ++i) {
            if(is_road[i]) continue; // select sign
            point pa = point(segs[i].a.first, segs[i].a.second);
            point pb = point(segs[i].b.first, segs[i].b.second);
            auto vec = (on_seg[segs[i].ai] > 1 ? pb - pa : pa - pb);
            for(int j = 0; j < n; ++j) {
                if(!is_road[j] || !isis_ss(segs[i], segs[j])) continue; // select related road
                auto v = point(segs[j].b.first - segs[j].a.first, segs[j].b.second - segs[j].a.second); // a to b
                if(abs(abs(arg(v / vec)) - pi / 2) < eps) {
                    can_use[segs[j].ai][segs[j].bi] = false;
                    can_use[segs[j].bi][segs[j].ai] = false;
                } else if(abs(arg(v / vec)) + eps < pi / 2) {
                    can_use[segs[j].ai][segs[j].bi] = false;
                } else {
                    can_use[segs[j].bi][segs[j].ai] = false;
                }
            }
        }

        graph g(m);
        for(int i = 0; i < m; ++i) {
            for(int j = 0; j < m; ++j) {
                if(i == j) continue;
                if(can_use[i][j]) {
                    add_edge(g, i, j, dist(ps[i], ps[j]));
                }
            }
        }
        vector<int> d(m, inf);
        vector<int> prev(m, -1);
        d[get_idx(sp)] = 0;
        priority_queue<pii, vector<pii>, greater<pii>> que;
        que.emplace(0, get_idx(sp));
        while(!que.empty()) {
            int cur_d, v;
            tie(cur_d, v) = que.top();
            que.pop();
            if(cur_d > d[v]) continue;
            for(auto const& e : g[v]) {
                if(d[e.to] > cur_d + e.cost) {
                    d[e.to] = cur_d + e.cost;
                    prev[e.to] = v;
                    que.emplace(cur_d + e.cost, e.to);
                }
            }
        }

        if(d[get_idx(gp)] == inf) {
            cout << -1 << endl;
        } else {
            int now = get_idx(gp);
            vector<pii> ans;
            while(now != -1) {
                if(is_intersection[now] >= 2) {
                    ans.push_back(ps[now]);
                }
                now = prev[now];
            }
            reverse(begin(ans), end(ans));
            for(auto& p : ans) {
                cout << p.first << ' ' << p.second << endl;
            }
            cout << 0 << endl;
        }
    }
}
accuracy: 1
time_ms: 100
memory_kb: 3248
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const double EPS = 1e-8;

typedef complex<double> P;
namespace std{
	bool operator < (const P& a, const P& b){
		return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
	}
}
double cross(const P& a, const P& b){
	return imag(conj(a)*b);
}
double dot(const P& a, const P& b){
	return real(conj(a)*b);
}

int ccw(P a, P b, P c){
	b -= a; c -= a;
	if(cross(b, c) > 0)   return +1;       // counter clockwise
	if(cross(b, c) < 0)   return -1;       // clockwise
	if(dot(b, c) < 0)     return +2;       // c--a--b on line
	if(norm(b) < norm(c)) return -2;       // a--b--c on line
	return 0;
}

struct L : public vector<P>{
	L(){}
	L(const P &a, const P &b){
		push_back(a); push_back(b);
	}
};


bool intersectLL(const L &l, const L &m){
	return abs(cross(l[1] - l[0], m[1] - m[0])) > EPS || // non-parallel
		abs(cross(l[1] - l[0], m[0] - l[0])) < EPS;   // same line
}

bool intersectSS(const L &s, const L &t){
	return ccw(s[0], s[1], t[0])*ccw(s[0], s[1], t[1]) <= 0 &&
		ccw(t[0], t[1], s[0])*ccw(t[0], t[1], s[1]) <= 0;
}

P crosspointLL(const L &l, const L &m){
	double A = cross(l[1] - l[0], m[1] - m[0]);
	double B = cross(l[1] - l[0], l[1] - m[0]);
	if(abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
	if(abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
	return m[0] + B / A * (m[1] - m[0]);
}

bool intersectSP(const L &s, const P &p){
	return abs(s[0] - p) + abs(s[1] - p) - abs(s[1] - s[0]) < EPS; // triangle inequality
}

struct Edge{
	int from, to;
	double cost;
};

typedef vector<vector<Edge>> Graph;

Graph segment_arrangement(const std::vector<L> &ss, std::vector<P> &ps){
	for(int i = 0; i < (int)ss.size(); ++i){  // O(n^2)
		ps.push_back(ss[i][0]);
		ps.push_back(ss[i][1]);
		for(int j = i + 1; j < (int)ss.size(); ++j)
			if(intersectSS(ss[i], ss[j])) ps.push_back(crosspointLL(ss[i], ss[j]));
	}
	std::sort(ps.begin(), ps.end());
	ps.erase(std::unique(ps.begin(), ps.end()), ps.end());
	Graph g(ps.size());
	for(int i = 0; i < (int)ss.size(); ++i){
		std::vector<std::pair<double, int>> list;
		for(int j = 0; j < (int)ps.size(); ++j)
			if(intersectSP(ss[i], ps[j]))
				list.push_back(std::make_pair(norm(ss[i][0] - ps[j]), j));
		std::sort(list.begin(), list.end());
		for(int j = 0; j + 1 < (int)list.size(); ++j){
			int a = list[j].second, b = list[j + 1].second;
			double len = abs(ps[a] - ps[b]);
			g[a].push_back({ a, b, len });
			g[b].push_back({ b, a, len });
		}
	}
	return g;
}

typedef pair<double, int> State;
const double INF = 1e18;
bool sign[200];

int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);
#ifdef LOCAL
	std::ifstream in("in");
	std::cin.rdbuf(in.rdbuf());
#endif

	int n;
	while(cin >> n, n){
		P start, goal;
		{
			int x, y;
			cin >> x >> y;
			start = P(x, y);
			cin >> x >> y;
			goal = P(x, y);
		}
		vector<L> ls(n);
		for(int i = 0; i < n; i++){
			int x1, y1, x2, y2;
			cin >> x1 >> y1 >> x2 >> y2;
			ls[i] = L(P(x1, y1), P(x2, y2));
		}
		vector<L> seg;
		for(int i = 0; i < n; i++){
			sign[i] = 0;
			int intersect[2] = { 0 };
			for(int j = 0; j < n; j++){
				if(i == j) continue;
				if(intersectSP(ls[j], ls[i][0])) intersect[0] = 1;
				if(intersectSP(ls[j], ls[i][1])) intersect[1] = 1;
			}
			assert(intersect[0] + intersect[1] >= 1);
			if(intersect[0] + intersect[1] == 1){
				sign[i] = 1;
				//cout << "sign " << i << endl;
			}
			else{
				seg.push_back(ls[i]);
			}
		}

		vector<P> ps;
		auto G = segment_arrangement(seg, ps);
		map<P, int> idxMap;
		for(int i = 0; i < ps.size(); i++){
			idxMap[ps[i]] = i;
		}

		set<pair<int, int>> NG;
		for(int i = 0; i < ps.size(); i++){
			for(auto e : G[i]){
				int u = i, v = e.to;
				P p0 = ps[u], p1 = ps[v];
				for(int j = 0; j < n; j++){
					if(!sign[j]) continue;
					int onIdx = -1;
					for(int k = 0; k < 2; k++){
						P sp = ls[j][k];
						if(ccw(p0, sp, p1) == -2 || ccw(p1, sp, p0) == -2){
							onIdx = k;
							break;
						}
					}
					if(onIdx == -1) continue;

					P sp0 = ls[j][onIdx], sp1 = ls[j][1 - onIdx];
					P v1 = p1 - p0, v2 = sp1 - sp0;
					int d = dot(v1, v2);
					if(d >= 0){
						NG.insert({ u, v });
						//cout << "NG " << (int)ps[u].real() << " " << (int)ps[u].imag() << " -> "
						//<< (int)ps[v].real() << " " << (int)ps[v].imag() << endl;
					}
				}
			}
		}

		vector<double> dist(ps.size(), INF);
		vector<int> pre(ps.size(), -1);
		priority_queue<State, vector<State>, greater<State>> q;
		q.push({ 0, idxMap[start] });
		dist[idxMap[start]] = 0;
		while(q.size()){
			int v = q.top().second;
			double d = q.top().first;
			q.pop();
			if(dist[v] < d) continue;
			for(auto e : G[v]){
				if(NG.count({ v,e.to })) continue;
				double nd = d + abs(ps[e.to] - ps[v]);
				if(dist[e.to] > nd){
					dist[e.to] = nd;
					pre[e.to] = v;
					q.push({ nd, e.to });
				}
			}
		}

		if(dist[idxMap[goal]] == INF){
			cout << -1 << endl;
			continue;
		}

		int cur = idxMap[goal];
		vector<int> path;
		while(true){
			path.push_back(cur);
			if(cur == idxMap[start]) break;
			cur = pre[cur];
		}
		reverse(path.begin(), path.end());
		for(auto pp : path){
			cout << (int)ps[pp].real() << " " << (int)ps[pp].imag() << endl;
		}
		cout << 0 << endl;
	}
}
accuracy: 1
time_ms: 20
memory_kb: 3344
final_rank: 11

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;

typedef complex<ll> P;
typedef pair<P,P> S;
typedef pair<double,P> State;

namespace std{
  bool operator < ( const P &a,const P &b){
    return (a.real()==b.real()?a.imag()<b.imag():a.real()<b.real());
  }
};

ll dot(P a,P b){ return real(b*conj(a)); }
ll cross(P a,P b){ return imag(b*conj(a)); }
int state(S s,P p){
  P a=s.first,b=s.second;
  if(a==p||b==p)return 0;
  if(cross(a-p,b-p)!=0)return 1;
  if(dot(a-p,b-p)>0)return 1;
  return -1;
}

bool check(P si,P ti,const vector<S> &v,const vector<S> &E,const vector<P> &C){
  for(int i=0;i<(int)C.size();i++)
    if( state( S(si,ti) , C[i] ) == -1 ) return false;

  for(int i=0;i<(int)v.size();i++){
    if(state(v[i],si)==1||state(v[i],ti)==1)continue;
    bool res=true;
    for(int j=0;j<(int)E.size();j++){
      if( state(S(si,ti),E[j].first ) !=-1 && state(S(si,ti),E[j].second) !=-1)continue;
      P ve;
      if( state(S(si,ti),E[j].first ) ==-1)ve=E[j].first-E[j].second;
      if( state(S(si,ti),E[j].second) ==-1)ve=E[j].second-E[j].first;
      if( dot(ti-si,ve) <= 0 ){
        res=false;
      }
    }
    if(res)return true;
  }


  
  return false;
}

P input(){
  ll x,y;
  cin>>x>>y;
  return P(x,y);
}

int main(){
  while(1){
    int n;
    cin>>n;
    if(n==0)break;
    vector<S> A,B,E;
    P si=input();
    P ti=input();
    for(int i=0;i<n;i++){
      S s;
      s.first=input();
      s.second=input();
      A.push_back(s);
    }
    for(int i=0;i<n;i++){
      int fc=0,sc=0;
      int fk=0,sk=0;
      for(int j=0;j<n;j++){
        if(i==j)continue;
        if(state(A[j],A[i].first)<=0)fc++;
        if(state(A[j],A[i].first)==-1)fk++;
        if(state(A[j],A[i].second)<=0)sc++;
        if(state(A[j],A[i].second)==-1)sk++;
      }
      bool flg=false;
      if(fc==0&&sk>0)flg=true;
      if(sc==0&&fk>0)flg=true;
      if(flg)E.push_back(A[i]);
      else B.push_back(A[i]);
    }
                               
    vector<P> C;
    for(int i=0;i<(int)B.size();i++){
      C.push_back(B[i].first);
      C.push_back(B[i].second);
    }
    //    C.push_back(si);
    //    C.push_back(ti);
    sort(C.begin(),C.end());
    C.erase(unique(C.begin(),C.end()),C.end());
    assert( *lower_bound(C.begin(),C.end(), si ) == si );
    assert( *lower_bound(C.begin(),C.end(), ti ) == ti );
    
    priority_queue< State ,vector<State> , greater<State> > Q;
    map<P,double> d;
    map<P,P> prev;
    
    for(int i=0;i<(int)C.size();i++){
      d[C[i]]=1e9;
      prev[C[i]]=P(-1,-1);
    }
    
    Q.push( State(0,si) );
    d[si]=0;
    while(!Q.empty()){
      State s=Q.top();
      Q.pop();
      P p=s.second;
      double cost=s.first;
      if(d[p]<cost)continue;
      
      for(int j=0;j<(int)C.size();j++){
        P to=C[j];
        if(p==to)continue;
        if(!check(p,to,B,E,C))continue;
        double ncost=cost;
        double dx=to.real()-p.real();
        double dy=to.imag()-p.imag();
        
        ncost+= sqrt(dx*dx+dy*dy);
        
        if(d[to]>ncost){
          d[to]=ncost;
          prev[to]=p;
          Q.push( State(ncost,to) );
        }
      }
    }

    if(d[ti]==1e9){
      cout<<-1<<endl;
    }else{
      vector<P> ans;
      P cur=ti;
      while(1){
        ans.push_back(cur);
        if(cur==si)break;
        cur=prev[cur];
        assert(cur!=P(-1,-1));
      }
      reverse(ans.begin(),ans.end());
      for(int i=0;i<(int)ans.size();i++){
        if(i>0&&ans[i]==ans[i-1])continue;
        cout<<ans[i].real()<<' '<<ans[i].imag()<<endl;
      }
      cout<<0<<endl;
    }
    
    //    printf("%.10f\n",d[ti]);
  }
  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3148
final_rank: 12

code_snippet: #include<bits/stdc++.h>
#define f first
#define s second
#define mp make_pair
#define pi M_PI
#define inf 1<<30
#define MAX 50000
#define eps (1e-11)
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):x(x),y(y){}

  Point operator+(Point p){ return Point(x+p.x,y+p.y);}
  Point operator-(Point p){ return Point(x-p.x,y-p.y);}
  Point operator*(double k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ return (x!=p.x ? x<p.x : y<p.y);}
  bool operator==(Point p)const{ return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

double norm(Vector a){ return (a.x*a.x+a.y*a.y);}
double abs(Vector a){ return sqrt(norm(a));}
double dot(Vector a,Vector b){ return (a.x*b.x+a.y*b.y);}
double cross(Vector a,Vector b){ return (a.x*b.y-a.y*b.x);}

int ccw(Point p0,Point p1,Point p2){
  Vector a=p1-p0;
  Vector b=p2-p0;
  if(cross(a,b)>eps)return 1;
  if(cross(a,b)<-eps)return -1;
  if(dot(a,b)<-eps)return 2;
  if(a.norm()<b.norm())return -2;
  return 0;
}

typedef vector<vector<int> > Graph;
typedef pair<double,int> P;

int n;
vector<Segment> vs,va,vb;

bool check(Segment s){
  for(int i=0;i<vb.size();i++){
    if(ccw(s.p1,s.p2,vb[i].p1)==0){
      Vector v1=(s.p1-vb[i].p1),v2=(vb[i].p2-vb[i].p1);
      double r=acos(dot(v1,v2)/(abs(v1)*abs(v2)))*180/pi;
      if(90-r<eps)return false;
    }
    if(ccw(s.p1,s.p2,vb[i].p2)==0){
      Vector v1=(s.p1-vb[i].p2),v2=(vb[i].p1-vb[i].p2);
      double r=acos(dot(v1,v2)/(abs(v1)*abs(v2)))*180/pi;
      if(90-r<eps)return false;
    }
  }
  return true;
}

Graph SegmentArrangement(vector<Segment> v,vector<Point> &ps){
  for(int i=0;i<v.size();i++){
    ps.push_back(v[i].p1);
    ps.push_back(v[i].p2);
  }
  sort(ps.begin(),ps.end());
  ps.erase(unique(ps.begin(),ps.end()),ps.end());
  Graph g(ps.size());
  for(int i=0;i<v.size();i++){
    vector<pair<double,int> > list;
    for(int j=0;j<ps.size();j++)
      if(ccw(v[i].p1,v[i].p2,ps[j])==0)
        list.push_back(mp(norm(v[i].p1-ps[j]),j));
    sort(list.begin(),list.end());
    for(int j=0;j<list.size()-1;j++){
      int a=list[j].s,b=list[j+1].s;
      if(check(Segment(ps[a],ps[b])))g[a].push_back(b);
      if(check(Segment(ps[b],ps[a])))g[b].push_back(a);
    }
  }
  return g;
}

Graph g;
vector<Point> vp;
int a=-1,b=-1;
Point s,t;

void init(){
  vs.clear();va.clear();vb.clear();vp.clear();
}

void dijkstra(){
  double d[MAX];
  int p[MAX];
  fill(d,d+MAX,inf);
  fill(p,p+MAX,-1);
  priority_queue<P,vector<P>,greater<P> > pq;
  pq.push(mp(0.0,a));
  d[a]=0.0;
  p[a]=a;

  while(pq.size()){
    P u=pq.top();
    pq.pop();
    if(d[u.s]-u.f<-eps)continue;
    for(int i=0;i<g[u.s].size();i++){
      int next=g[u.s][i];
      double dis=abs(vp[u.s]-vp[next]);
      if(u.f+dis-d[next]<-eps){
        d[next]=u.f+dis;
        p[next]=u.s;
        pq.push(mp(u.f+dis,next));
      }
    }
  }
  if(p[b]==-1){
    cout<<-1<<endl;
    return;
  }
  vector<Point> ans;
  int now=b;
  while(p[now]!=now){
    ans.push_back(vp[now]);
    now=p[now];
  }
  ans.push_back(vp[now]);
  reverse(ans.begin(),ans.end());
  for(int i=0;i<ans.size();i++)cout<<ans[i].x<<" "<<ans[i].y<<endl;
  cout<<0<<endl;
}

int main()
{
  while(1){
    cin>>n;
    if(n==0)break;
    init();
    cin>>s.x>>s.y>>t.x>>t.y;
    for(int i=0;i<n;i++){
      int a,b,c,d;
      cin>>a>>b>>c>>d;
      vs.push_back(Segment(Point(a,b),Point(c,d)));
    }
    for(int i=0;i<n;i++){
      bool left=false,right=false;
      for(int j=0;j<n;j++){
        if(i==j)continue;
        if(ccw(vs[j].p1,vs[j].p2,vs[i].p1)==0)left=true;
        if(ccw(vs[j].p1,vs[j].p2,vs[i].p2)==0)right=true;
      }
      if(left && right)va.push_back(vs[i]);
      else vb.push_back(vs[i]);
    }
    g=SegmentArrangement(va,vp);
    for(int i=0;i<vp.size();i++){
      if(vp[i]==s)a=i;
      if(vp[i]==t)b=i;
    }
    dijkstra();
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 2024
final_rank: 5

code_snippet: #include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <complex>
#include <queue>
#include <deque>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <iomanip>
#include <assert.h>
#include <array>
#include <cstdio>
#include <cstring>
#include <random>
#include <functional>
#include <numeric>
#include <bitset>
#include <fstream>

using namespace std;

#define REP(i,a,b) for(int i=a;i<(int)b;i++)
#define rep(i,n) REP(i,0,n)
#define all(c) (c).begin(), (c).end()
#define zero(a) memset(a, 0, sizeof a)
#define minus(a) memset(a, -1, sizeof a)
#define watch(a) { cout << #a << " = " << a << endl; }
template<class T1, class T2> inline bool minimize(T1 &a, T2 b) { return b < a && (a = b, 1); }
template<class T1, class T2> inline bool maximize(T1 &a, T2 b) { return a < b && (a = b, 1); }

typedef long long ll;
int const inf = 1<<29;

struct xor128 {
  unsigned x,y,z,w;
  xor128(): x(random_device()()), y(157892372), z(7777777), w(757328) {}
  unsigned next() {
    unsigned t=x^(x<<11);
    x=y;y=z;z=w;
    return w=w^(w>>19)^t^(t>>8);
  }
  unsigned next(unsigned k) {
    return next()%k;
  }
} rndgen;


typedef complex<double> P;

namespace std {

bool operator < (P const& l, P const& r) {
  return abs(l.real() - r.real()) < 1e-5 ? l.imag() < r.imag() : l.real() < r.real();
}

}

namespace point_2d {

using Real = double;

Real const EPS = 1e-5;  // !!! DO CHECK EPS !!!

//bool operator < (P const& l, P const& r) {  return abs(l.real() - r.real()) < EPS ? l.imag() < r.imag() : l.real() < r.real();}

bool operator > (P const& l, P const& r) {
  return abs(l.real() - r.real()) < EPS ? l.imag() > r.imag() : l.real() > r.real();
}

bool equals(Real a, Real b) {
  return abs(a - b) < EPS;
}

bool equals (P const& l, P const& r) {
  return abs(l - r) < EPS;
}

struct Line : public pair<P, P> {
  Line(P const& a, P const& b) { first = a, second = b; }
  const P& operator[] (int x) const { return x == 0 ? first : second; }
  P& operator[] (int x) { return x == 0 ? first : second; }
};
typedef Line Segment;

bool operator < (const Line& a, const Line& b) {
  return a[0] != b[0] ? a[0] < b[0] : a[1] < b[1];
}

struct Circle {
  P p; Real r;
  Circle(){}
  Circle(P const& p, Real r): r(r) { this->p = p; }
};

struct Polygon : public vector<P> {
  vector<P>& g = *this;
  Polygon() = default;
  Polygon(vector<P> const& g) { this->g = g; }
  P& operator[] (int x) { return vector<P>::operator[]((x + size()) % size()); }
  Segment side(int x) { return std::move(Segment(this->operator[](x), this->operator[](x+1))); }
  Segment backside(int x) { return std::move(Segment(this->operator[](x), this->operator[](x-1))); }
};

Real cross(P const& a, P const& b) { return imag(conj(a)*b); }
Real dot(P const& a, P const& b) { return real(conj(a)*b); }
Real cos(P const& l, P const& r) { return dot(l, r) / (abs(l) * abs(r)); }  // not verified

enum ccw_result {
  counter_clockwise = +1, clockwise = -1, online_back = +2, online_front = -2, on_segment = 0
};

ccw_result ccw(P a, P b, P c) {
  b -= a, c -= a;
  if(cross(b, c) > 0)   { return ccw_result::counter_clockwise; }
  if(cross(b, c) < 0)   { return ccw_result::clockwise; }
  if(dot(b, c) < 0)     { return ccw_result::online_back; }
  if(norm(b) < norm(c)) { return ccw_result::online_front; }
  return ccw_result::on_segment;
}

bool intersect_lp(Line const& l, P const& p) {
  return abs(cross(l[1]-p, l[0]-p)) < EPS;
}

bool intersect_sp(Line const& s, P const& p) {
  return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS; // triangle inequality
}

bool intersect_ss(Segment const& s, Segment const& t) {
  return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= EPS &&
         ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= EPS;
}

bool intersect_ll(Line const& l, Line const& m) {
  return abs(cross(l[1]-l[0], m[1]-m[0])) > EPS || // non-parallel
         abs(cross(l[1]-l[0], m[0]-l[0])) < EPS;   // same line
}

bool intersect_ls(Line const& l, Segment const& s) {
  return cross(l[1]-l[0], s[0]-l[0])*       // s[0] is left of l
         cross(l[1]-l[0], s[1]-l[0]) < EPS; // s[1] is right of l
}

P projection(Line const& l, P const& p) {
  auto t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
  return l[0] + t*(l[0]-l[1]);
}

P reflection(Line const& l, P const& p) {
  return p + (Real)2.0 * (projection(l, p) - p);
}

Real distance_sp(Line const& s, P const& p) {
  P const r = projection(s, p);
  if(intersect_sp(s, r)) return abs(r - p);
  return min(abs(s[0] - p), abs(s[1] - p));
}

Real distance_lp(Line const& l, P const& p) {
  return abs(p - projection(l, p));
}

bool intersect_cl(Circle const& c, Line const& l) {
  return distance_lp(l, c.p) <= c.r + EPS;
}

bool intersect_cs(Circle const& c, Line const& l) {
  if(abs(l[0] - c.p) < c.r - EPS && abs(l[1] - c.p) < c.r - EPS) { return false; }
  return distance_lp(l, c.p) <= c.r + EPS;
}

bool intersect_gs(Polygon const& g, Segment const& s) { // not verified
  auto u = const_cast<Polygon&>(g);
  rep(i, g.size()) {
    if(!intersect_sp(s, u[i]) && intersect_ss(s, u.side(i))) { return true; }
  }
  return false;
}

P crosspoint(const Line &l, const Line &m) {
  auto A = cross(l[1] - l[0], m[1] - m[0]);
  auto B = cross(l[1] - l[0], l[1] - m[0]);
  if(abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
  if(abs(A) < EPS) assert(false && "PRECONDITION NOT SATISFIED");
  return m[0] + B / A * (m[1] - m[0]);
}

pair<P, P> crosspoint(Circle const& c, Line const& l) {
  auto h = projection(l, c.p);
  auto e = (l[1]-l[0]) / abs(l[1]-l[0]);
  auto base = sqrt(c.r*c.r-abs(h-c.p)*abs(h-c.p));
  return {h+e*base, h-e*base};
}

pair<P, P> crosspoint(Circle c1, Circle c2) {
  if(c1.p.real() > c2.p.real()) swap(c1, c2);
  auto const d = abs(c2.p - c1.p);
  auto const alpha  = acos((c2.p.real() - c1.p.real()) / d) * ((c1.p.imag() > c2.p.imag()) ? -1.0 : 1.0);
  auto const beta   = acos((c1.r * c1.r - c2.r * c2.r + d * d) / 2.0 / d / c1.r);
  return make_pair(c1.p + polar(c1.r, alpha - beta), c1.p + polar(c1.r, alpha + beta));
}
 
vector<P> tangent_points(Circle const& c, P const& p) {
  vector<P> ret;
  auto const sec2 = norm(p - c.p);
  auto const tan2 = max(Real(0), sec2 - c.r * c.r);
  auto const nv = (p - c.p) * c.r * c.r / sec2;
  auto const pv = (p - c.p) * P(0, -1) * c.r * sqrt(tan2) / sec2;
  ret.push_back(c.p + nv + pv);
  ret.push_back(c.p + nv - pv);
  return ret;
}

// テゥツ?堙・ツクツクclangテ」ツ?ァテ」ツ?づ」ツつ古」ツ?ーテ」ツ??(x, y)"テ」ツ?ョテ・ツスツ「テ・ツシツ湘」ツつ津ィツェツュテ」ツ?ソテ・ツ渉姪」ツつ凝」ツ?古」ツ??」ツ?禿」ツつ古」ツつ?x y"テ」ツ?ォテ・ツ、ツ嘉ヲツ崢エテ」ツ?凖」ツつ?
istream& operator >> (istream& is, P& p) { Real x, y; is >> x >> y; p = P(x, y); return is; }
ostream& operator << (ostream& os, Line const& l) { return os << "{" << l[0] << ", " << l[1] << "}"; }

}
using namespace point_2d;



int N;
P src, dst;
vector<Line> line;
vector<vector<pair<int, double>>> G;
map<pair<int, int>, int> nd;
map<int, P> ndB;
int nsize;

template<class T> using PQ_G = priority_queue<T, vector<T>, greater<T>>;

void dijkstra(int s, int t) {

  vector<double> dist(222, inf);
  vector<int> prev(222, inf);
  dist[s] = 0;

  PQ_G<pair<double, int>> pq;
  pq.emplace(0, s);

  while(!pq.empty()) {
    double len; int pos; tie(len, pos) = pq.top(); pq.pop();
    for(auto const& e: G[pos]) {
      int next; double plen; tie(next, plen) = e;
//      cout << pos << " -> " << next << endl;
      if(dist[next] <= len + plen) continue;
      dist[next] = len + plen;
      prev[next] = pos;
      pq.emplace(dist[next], next);
    }
  }

//  cout << s << ", " << t << endl;  cout << dist[s] << ", " << dist[t] << endl;

  if(dist[t] == inf) {
    cout << -1 << endl;
  }
  else {
    vector<pair<int, int>> path;
    for(int pos = t; pos != s; pos = prev[pos]) {
      assert(pos != inf);
      path.emplace_back((int)ndB[pos].real(), (int)ndB[pos].imag());
    }
    cout << (int)ndB[s].real() << " " << (int)ndB[s].imag() << endl;
//    cout << s << endl;
    reverse(all(path));
    for(auto& e: path)
      cout << e.first << " " << e.second << endl;
//      cout << nd[e] << endl;
    cout << "0\n";
  }

}

bool merge_if_able(Line &s, Line t) {
  if (abs(cross(s[1]-s[0], t[1]-t[0])) > EPS) return false;
  if (ccw(s[0], t[0], s[1]) == +1 ||
      ccw(s[0], t[0], s[1]) == -1) return false; // not on the same line
  if (ccw(s[0], s[1], t[0]) == -2 ||
      ccw(t[0], t[1], s[0]) == -2) return false; // separated
  s = Line(min(s[0], t[0]), max(s[1], t[1]));
  return true;
}
void merge_segments(vector<Line>& segs) {
  for (int i = 0; i < segs.size(); ++i)
    if (segs[i][1] < segs[i][0])
      swap(segs[i][1], segs[i][0]);
  for (int i = 0; i < segs.size(); ++i)
    for (int j = i+1; j < segs.size(); ++j)
      if (merge_if_able(segs[i], segs[j]))
        segs[j--] = segs.back(), segs.pop_back();
}

void split_segments(vector<Line>& segs, vector<P> const& pts) {
  vector<Line> nsegs;
  rep(i, segs.size()) {
    vector<P> v = {segs[i][0], segs[i][1]};
    rep(j, pts.size()) {
      if(intersect_sp(segs[i], pts[j]) && !equals(segs[i][0], pts[j]) && !equals(segs[i][1], pts[j])) {
//        cout << "check" << endl;
        v.push_back(pts[j]);
      }
    }
    sort(all(v));
    rep(i, v.size() - 1) {
      nsegs.push_back(Line(v[i], v[i+1]));
    }
  }

  segs = nsegs;
}

void solve() {

  double x, y;
  cin >> x >> y;
  src = P(x, y);
  cin >> x >> y;
  dst = P(x, y);

  rep(i, N) {
    P p1; cin >> x >> y; p1 = P(x, y);
    P p2; cin >> x >> y; p2 = P(x, y);
    line.push_back(Line(p1, p2));
  }

  map<pair<int, int>, int> cnt;
  rep(i, N) {
    REP(j, i+1, N) {
      if(intersect_ss(line[i], line[j])) {
        auto p = crosspoint(line[i], line[j]);
        cnt[{p.real(), p.imag()}]++;
      }
    }
  }

  #define reg_node(node) \
    {nd[{node.real(),node.imag()}] = nsize, ndB[nsize++] = node;}

  reg_node(src);
  reg_node(dst);

  #define new_node(p) \
    nd.find({p.real(), p.imag()}) == nd.end()

  rep(i, N) {
    auto p = line[i][0];
    auto q = line[i][1];
    if(cnt[{p.real(), p.imag()}] > 0 && cnt[{q.real(), q.imag()}] > 0) {
      if(new_node(p))
        reg_node(p);
      if(new_node(q))
        reg_node(q);
    }
  }

  #define road(l) \
    (nd.find({l[0].real(),l[0].imag()}) != nd.end() && nd.find({l[1].real(),l[1].imag()}) != nd.end())

  vector<Line> nl;

  set<int> del;

  rep(i, N) {
    if(road(line[i])) {
      REP(j, i+1, N) {
        if(road(line[j])) {
          if(intersect_ss(line[i], line[j])) {
            auto cp = crosspoint(line[i], line[j]);
            if(new_node(cp))
              reg_node(cp);
            if(!(equals(cp, line[i][0]) || equals(cp, line[i][1])) &&
               (equals(cp, line[j][0]) || equals(cp, line[j][1]))) {
              nl.push_back(Line(line[i][0], cp));
              nl.push_back(Line(line[i][1], cp));
              del.insert(i);
            }
            else if((equals(cp, line[i][0]) || equals(cp, line[i][1])) &&
               !(equals(cp, line[j][0]) || equals(cp, line[j][1]))) {
              nl.push_back(Line(line[j][0], cp));
              nl.push_back(Line(line[j][1], cp));
              del.insert(j);
            }
            else /*if((equals(cp, line[i][0]) || equals(cp, line[i][1])) &&
//               (equals(cp, line[j][0]) || equals(cp, line[j][1])))*/ {
            }
          }
        }
      }
    }
  }

  vector<Line> signs;

  rep(i, N) {
    if(road(line[i]) && !del.count(i))
      nl.push_back(line[i]);
    if(!road(line[i])) {
      auto sign = line[i];
      rep(k, line.size()) {
        if(road(line[k]) && intersect_ss(line[k], sign)) {
          auto cp = crosspoint(line[k], sign);
          if(equals(sign[1], cp))
            swap(sign[0], sign[1]);
          signs.push_back(sign);
          break;
        }
      }
    }
  }

  merge_segments(nl);
  vector<P> pts;
  for(auto& e: nd)
    pts.push_back(P(e.first.first, e.first.second));
  split_segments(nl, pts);

  sort(all(nl));
  nl.erase(unique(all(nl)), nl.end());
/*
  visualizer::init();  drawlines(nl);  drawlines(signs);

  for(auto& e: nd) {
    P k = P(e.first.first, e.first.second);
    visualizer::point(k);
    visualizer::label(k, to_string(nd[{k.real(),k.imag()}]));
  }
*/

  #define corresponds_sign(r, s)  \
    intersect_ss(r, s)

  auto can_go = [&](P p, P s, P o) {
    return dot(p-s, o-s) > EPS;
  };

  set<pair<int, int>> invalids;

  rep(i, nl.size()) {
    rep(j, signs.size()) {
      if(corresponds_sign(nl[i], signs[j])) {
        auto& tar = nl[i];
        auto& sign = signs[j];
        if(!can_go(tar[0], sign[0], sign[1]))
          invalids.insert({nd[{tar[0].real(), tar[0].imag()}], nd[{tar[1].real(), tar[1].imag()}]});

        if(!can_go(tar[1], sign[0], sign[1]))
          invalids.insert({nd[{tar[1].real(), tar[1].imag()}], nd[{tar[0].real(), tar[0].imag()}]});
      }
    }
  }

  rep(i, nl.size()) {
    auto& tar = nl[i];
    auto s = nd[{tar[0].real(), tar[0].imag()}];
    auto t = nd[{tar[1].real(), tar[1].imag()}];
    if(!invalids.count({s, t}))
      G[s].emplace_back(t, abs(tar[0]-tar[1]));
    if(!invalids.count({t, s}))
      G[t].emplace_back(s, abs(tar[0]-tar[1]));
  }

//  graph::visualizer::directed_graph(G);  visualizer::show_picture();

  dijkstra(nd[{src.real(),src.imag()}], nd[{dst.real(), dst.imag()}]);
}

void init() {
  line.clear();
  G.resize(222);
  rep(i, 222) G[i].clear();
  nsize = 0;
  nd.clear();
  ndB.clear();
}

int main() {
  while(cin >> N && N) {
    init();
    solve();
  }
}
accuracy: 1
time_ms: 10
memory_kb: 3232
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std; 

#define ALL(x) (x).begin(),(x).end() 
#define EACH(i,c) for(auto i=(c).begin();i!=(c).end();++i)

typedef long long ll;
const double eps = 1e-10;
# 1 "src/aoj1279.cpp"
# 1 "<????????????>"
# 1 "<?????????????????????>"
# 1 "src/aoj1279.cpp"
const double INF = 1e+10;
typedef double Weight;
struct Edge{
    int from, to;
    Weight weight;
    int rev;
    Edge(int from, int to, Weight weight) :
        from(from), to(to), weight(weight) { }
    Edge(int from, int to, Weight weight, int rev) :
        from(from), to(to), weight(weight), rev(rev){ }
};
bool operator < (const Edge &a, const Edge &b){
    if(a.weight != b.weight) return a.weight > b.weight;
    if(a.from != b.from) return a.from > b.from;
    return a.to > b.to;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void addFlowEdge(Graph &g, int a, int b, Weight c){
    g[a].push_back(Edge(a, b, c, g[b].size()));
    g[b].push_back(Edge(b, a, 0, g[a].size() - 1));
}
void addUndirectedEdge(Graph &g, int a, int b, Weight c){
    g[a].push_back(Edge(a, b, c, g[b].size()));
    g[b].push_back(Edge(b, a, c, g[a].size() - 1));
}
void dijkstra(const Graph &g, int s, vector<Weight> &dist, vector<int> &prev){
    int n = g.size();
    dist.assign(n, INF);
    dist[s] = 0;
    prev.assign(n, -1);
    priority_queue<Edge> Q;
    Q.push(Edge(-2, s, 0));
    while(!Q.empty()){
        Edge e = Q.top(); Q.pop();
        if(prev[e.to] != -1) continue;
        prev[e.to] = e.from;
        EACH(i, g[e.to]){

            if(dist[i -> to] > dist[i -> from] + i -> weight){
                dist[i -> to] = dist[i -> from] + i -> weight;
                Q.push(Edge(i -> from, i -> to, dist[i -> to]));
            }
        }
    }
}
vector<int> buildPath(const vector<int> &prev, int t){
    vector<int> path;
    for(int v = t; v >= 0; v = prev[v])
        path.push_back(v);
    reverse(path.begin(), path.end());
    return path;
}
# 1 "src/../../geometry/geometry.cpp" 1
const double PI = atan(1) * 4;

int sgn(double a){
    return a < -eps ? -1: a > eps ? 1: 0;
}
int sgn(double a, double b){
    return sgn(b - a);
}
typedef complex<double> P;
typedef vector<P> Polygon;
struct Line : public vector<P> {
    Line(P a, P b) {
        push_back(a); push_back(b);
    }
};
struct Segment : public Line {
    Segment(const P &a, const P &b) : Line(a,b) { }
};
struct Circle{
    P o;
    double r;
    Circle() { }
    Circle(const P &o, double r) : o(o), r(r) { }
    Circle(double x, double y, double r) : o(x,y), r(r) { }

    bool contains(const P &p) const{
        return sgn(abs(p-o), r) <= 0;
    }

    bool inside(const P &p) const{
        return sgn(abs(p-o), r) < 0;
    }

    pair<Line,Line> tangent(const P &p) const{
        vector<Line> res;
        double d = abs(p - o), s = r*r / d, t = sqrt(r*r-s*s);
        P q = o + s/d * (p - o), e = (p - o) * P(0, 1/d);
        return make_pair(Line(p,q+e*t), Line(p,q-e*t));
    }
};

bool near(const P &a, const P &b){
    return !sgn(abs(a-b));
}

bool lessX(const P &a, const P &b){
    if(sgn(real(a), real(b))) return real(a) < real(b);
    if(sgn(imag(a), imag(b))) return imag(a) < imag(b);
    return false;
}
bool lessY(const P &a, const P &b){
    if(sgn(imag(a), imag(b))) return imag(a) < imag(b);
    if(sgn(real(a), real(b))) return real(a) < real(b);
    return false;
}
double dot(const P &a, const P &b){
    return real(conj(a) * b);
}
double cross(const P &a, const P &b){
    return imag(conj(a) * b);
}
int ccw(const P &a, P b, P c){
    assert(!near(a, b));
    b -= a; c -= a;
    if (sgn(cross(b, c)) > 0) return +1;
    if (sgn(cross(b, c)) < 0) return -1;
    if (sgn(dot(b, c)) < 0) return +2;
    if (sgn(norm(b), norm(c)) > 0) return -2;
    return 0;
}
bool parallel(const Line &s, const Line &t){
    return !sgn(abs(cross(s[1]-s[0], t[1]-t[0])));
}
bool orthogonal(const Line &s, const Line &t){
    return !sgn(abs(dot(s[1]-s[0], t[1]-t[0])));
}

P projection(const Line &s, const P &a){
    P v = s[1] - s[0];
    return s[0] + dot(v, a - s[0]) / abs(v) / abs(v) * v;
}

P reflection(const Line &s, const P &a){
    P p = projection(s, a);
    return 2.0 * p - a;
}
# 58 "src/aoj1279.cpp" 2
# 1 "src/../../geometry/crosspoint.cpp" 1

bool intersectSS(const Segment &s, const Segment &t){
    return ccw(s[0],s[1],t[0]) * ccw(s[0],s[1],t[1]) <= 0 &&
            ccw(t[0],t[1],s[0]) * ccw(t[0],t[1],s[1]) <= 0;
}

P crosspointSS(const Segment &s, const Segment &t){
    double a = cross(s[1] - s[0], t[1] - t[0]);
    double b = cross(s[1] - s[0], s[1] - t[0]);
    if(!sgn(abs(a)) && !sgn(abs(b))) return s[0];

    return t[0] + b/a * (t[1] - t[0]);
}
P crosspointLL(const Line &s, const Line &t){
    double a = cross(s[1] - s[0], t[1] - t[0]);
    double b = cross(s[1] - s[0], s[1] - t[0]);
    if(!sgn(abs(a)) && !sgn(abs(b))) return s[0];

    return t[0] + b/a * (t[1] - t[0]);
}

double distanceLP(const Line &s, const P &p){
    return abs(cross(p-s[0],s[1]-s[0])) / abs(s[1]-s[0]);
}

double distanceSP(const Segment &s, const P &p){
    if(min(dot(s[1]-s[0], p-s[0]), dot(s[0]-s[1], p-s[1])) < 0)
        return min(abs(p-s[0]), abs(p-s[1]));
    else
        return distanceLP(s, p);

}

double distanceSS(const Segment &s, const Segment &t){
    if(intersectSS(s, t)) return 0;
    return min( min(distanceSP(s, t[0]), distanceSP(s, t[1])),
                min(distanceSP(t, s[0]), distanceSP(t, s[1])));
}

pair<P,P> crosspointCC(const Circle &a, const Circle &b){
    double d = abs(b.o - a.o);
    double x = (a.r * a.r - b.r * b.r + d * d) / (d * 2);
    P v = (b.o - a.o) * (1.0 / d);
    P n = P(0,1) * v;
    double h = sqrt(a.r * a.r - x * x);
    return make_pair(a.o + v * x + n * h,
                     a.o + v * x - n * h);
}


int intersectLC(const Line &l, const Circle &c){
    double d = distanceLP(l, c.o);
    return sgn(d, c.r) + 1;
}



vector<P> crosspointLC(const Line &l, const Circle &c){
    int n = intersectLC(l, c);
    vector<P> res;
    if(!n) return res;
    P p = projection(l, c.o), e = 1.0/abs(l[1]-l[0])*(l[1]-l[0]);
    if(n == 1){
        res.push_back(p); return res;
    }
 if(sgn(abs(p - c.o)))
  e = (p - c.o) * P(0, 1/abs(p - c.o));
    double d = sqrt(c.r*c.r-norm(p-c.o));
    res.push_back(p + e * d);
    res.push_back(p - e * d);
    return res;
}
# 59 "src/aoj1279.cpp" 2
# 1 "src/../../geometry/arrangement.cpp" 1


Graph segmentArrangement(const vector<Segment> &ss, vector<P> &ps){
    for(int i = 0; i < ss.size(); ++i){
        ps.push_back(ss[i][0]);
        ps.push_back(ss[i][1]);
        for(int j=i+1;j<ss.size();++j){
            if(intersectSS(ss[i], ss[j]))
                ps.push_back(crosspointSS(ss[i], ss[j]));
        }
    }
    sort(ALL(ps), lessX); ps.erase(unique(ALL(ps), near), ps.end());
    Graph g(ps.size());
    for(int i=0;i<ss.size();++i){
        vector<pair<double, int> > lst;
        for(int j=0;j<ps.size();++j){
            if(ccw(ss[i][0], ss[i][1], ps[j]) == 0)
                lst.push_back(make_pair(norm(ss[i][0]-ps[j]), j));
        }
        sort(ALL(lst));
        for(int j=0;j+1<lst.size();++j){
            int a = lst[j].second, b = lst[j+1].second;
            addUndirectedEdge(g, a, b, abs(ps[a]-ps[b]));
        }
    }
    return g;
}
# 60 "src/aoj1279.cpp" 2

int main(){
    for(;;){
        int n;
        cin >> n;
        if(n == 0) return 0;
        P s, g;
        vector<Segment> v;
        int x, y;
        cin >> x >> y; s=P(x,y);
        cin >> x >> y; g=P(x,y);
        for(int i = 0; i < n; ++i){
            int x1, y1, x2, y2;
            cin >> x1 >> y1 >> x2 >> y2;
            v.push_back(Segment(P(x1,y1), P(x2,y2)));
        }
        vector<Segment> road, signs;
        for(int i = 0; i < n; ++i){
            int f = 0;
            for(int j=0;j<n;++j) if(i != j) for(int k=0;k<2;++k){
                if(ccw(v[j][0], v[j][1], v[i][k]) == 0)
                    f |= 1 << k;
            }
            if(f == 3) road.push_back(v[i]);
            else signs.push_back(v[i]);
        }
        vector<P> ps;
        Graph graph = segmentArrangement(road, ps);
        int si, gi;
        for(int i=0;i<ps.size();++i) if(abs(ps[i]-s) < eps) si = i;
        for(int i=0;i<ps.size();++i) if(abs(ps[i]-g) < eps) gi = i;

        EACH(i, signs){
            Segment ss = *i;
            EACH(j, graph) EACH(k, *j) {
                int a = k->from, b = k->to;
                bool f = true;
                double d = 1;
                if(ccw(ps[a], ps[b], ss[0]) == 0){
                    d = dot(ss[0]-ss[1], ps[b]-ps[a]);
                }
                else if(ccw(ps[a], ps[b], ss[1]) == 0){
                    d = dot(ss[1]-ss[0], ps[b]-ps[a]);
                }
                if(d < eps){
                    k->weight = INF;
                }
            }
        }

        vector<int> prev(ps.size(),-1);
        vector<Weight> dist(ps.size());
        dijkstra(graph, si, dist, prev);
        if(dist[gi] == INF){
            cout << -1 << endl;
        }
        else{
            vector<int> path = buildPath(prev, gi);
            EACH(i, path){
                cout << (int)ps[*i].real() << " " << (int)ps[*i].imag() << endl;
            }
            cout << 0 << endl;
        }
    }
}
accuracy: 1
time_ms: 20
memory_kb: 3252
final_rank: 10

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
template<class T>
using Table = vector<vector<T>>;
const ld eps=1e-9;
/* ??????????????¬ */

#include <complex>

typedef long double ld;
typedef complex<ld> Point;
#define REP(i,n) for(int i=0;i<(int)(n);i++)
#define ALL(x) (x).begin(),(x).end()


const ld pi = acos(-1.0);
const ld dtop = pi / 180.;
const ld ptod = 1. / dtop;

namespace std {
	bool operator<(const Point &lhs, const Point &rhs) {
		if (lhs.real() < rhs.real() - eps) return true;
		if (lhs.real() > rhs.real() + eps) return false;
		return lhs.imag() < rhs.imag();
	}
}

// ????????\???
Point input_point() {
	ld x, y;
	cin >> x >> y;
	return Point(x, y);
}

// ????????????????????????
bool eq(const ld a, const ld b) {
	return (abs(a - b) < eps);
}

// ??????
ld dot(const Point& a, const Point& b) {
	return real(conj(a) * b);
}

// ??????
ld cross(const Point& a, const Point& b) {
	return imag(conj(a) * b);
}

// ??´????????????
class Line {
public:
	Point a, b;
	Line() : a(Point(0, 0)), b(Point(0, 0)) {}
	Line(Point a, Point b) : a(a), b(b) {}
	Point operator[](const int _num)const {
		if (_num == 0)return a;
		else if (_num == 1)return b;
		else {
			assert(false);
			return Point();
		}
	}
};

// ????????????
class Circle {
public:
	Point p;
	ld r;
	Circle() : p(Point(0, 0)), r(0) {}
	Circle(Point p, ld r) : p(p), r(r) {}
};

// CCW
int ccw(const Point& a, const Point &b, const Point &c) {
	const Point nb(b - a);
	const Point nc(c - a);
	if (cross(nb, nc) > eps) return 1;   // a,b,c??????????¨???¨?????????????????¶
	if (cross(nb, nc) < -eps) return -1; // a,b,c???????¨???¨?????????????????¶
	if (dot(nb, nc) < 0) return 2;       // c,a,b???????????´???????????¶
	if (norm(nb) < norm(nc)) return -2;  // a,b,c???????????´???????????¶
	return 0;                          // a,c,b???????????´???????????¶
}


/* ???????????? */

// ??´?????¨??´??????????????????
bool isis_ll(const Line& l, const Line& m) {
	return !eq(cross(l.b - l.a, m.b - m.a), 0);
}

// ??´?????¨?????????????????????
bool isis_ls(const Line& l, const Line& s) {
	return isis_ll(l, s) &&
		(cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < eps);
}

// ????????¨?????????????????????
bool isis_ss(const Line& s, const Line& t) {
	return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 &&
		ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

// ????????´????????????
bool isis_lp(const Line& l, const Point& p) {
	return (abs(cross(l.b - p, l.a - p)) < eps);
}

// ?????????????????????
bool isis_sp(const Line& s, const Point& p) {
	ld n= (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}

// ??????????¶?
Point proj(const Line &l, const Point& p) {
	ld t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
	return l.a + t * (l.a - l.b);
}

// ??´?????¨??´????????????
Point is_ll(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	assert(cross(sv, tv) != 0);
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}
// ??´?????¨??´????????????
vector<Point> is_ll2(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	if (cross(sv, tv) != 0)return vector<Point>(1, is_ll(s, t));
	else {
		vector<Point>ans;
		for (int k = 0; k < 2; ++k) {
			if (isis_sp(s, t[k]) && find(ans.begin(), ans.end(), t[k]) == ans.end())ans.push_back(t[k]);
			if (isis_sp(t, s[k]) && find(ans.begin(), ans.end(), s[k]) == ans.end())ans.push_back(s[k]);
		}
		return ans;
	}
}
// ????????¨???????????????
//???????????£????????¨???????????¨assert(false)
Point is_ss(const Line &s, const Line& t) {
	if (isis_ss(s, t)) {
		for (int k = 0; k < 2; ++k) {
			for (int l = 0; l < 2; ++l) {
				if (s[k] == t[l])return s[k];
			}
		}
		return is_ll(s, t);
	}
	else {
		//??????isis_ss?????????
		assert(false);
		return Point(0, 0);
	}
}
// ????????¨???????????????
vector<Point> is_ss2(const Line &s, const Line& t) {
	vector<Point> kouho(is_ll2(s, t));
	vector<Point>ans;
	for (auto p : kouho) {
		if (isis_sp(s, p) && isis_sp(t, p))ans.emplace_back(p);
	}
	return ans;
}
// ??´?????¨???????????¢
ld dist_lp(const Line& l, const Point& p) {
	return abs(p - proj(l, p));
}

// ??´?????¨??´???????????¢
ld dist_ll(const Line& l, const Line& m) {
	return isis_ll(l, m) ? 0 : dist_lp(l, m.a);
}

// ??´?????¨??????????????¢
ld dist_ls(const Line& l, const Line& s) {
	return isis_ls(l, s) ? 0 : min(dist_lp(l, s.a), dist_lp(l, s.b));
}

// ????????¨???????????¢
ld dist_sp(const Line& s, const Point& p) {
	Point r = proj(s, p);
	return isis_sp(s, r) ? abs(r - p) : min(abs(s.a - p), abs(s.b - p));
}

// ????????¨??????????????¢
ld dist_ss(const Line& s, const Line& t) {
	if (isis_ss(s, t)) return 0;
	return min({ dist_sp(s, t.a), dist_sp(s, t.b), dist_sp(t, s.a), dist_sp(t, s.b) });
}


//??´?????¨??´?????????????????????????????????
Line bisection(const Line &s, const Line &t) {
	const Point laglanju(is_ll(s, t));
	const Point avec = !(abs(laglanju - s[0])<eps) ? s[0] - laglanju : s[1] - laglanju;
	const Point bvec = !(abs(laglanju - t[0])<eps) ? t[0] - laglanju : t[1] - laglanju;

	return Line(laglanju, laglanju + (abs(bvec)*avec + abs(avec)*bvec) / (abs(avec) + abs(bvec)));
}


//???????????´?????????????????????
//???????????´??????????????§???????????¨????¢?????????¨?????????
Point  inner_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i <static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (vertics[0] == vertics[1] || vertics[1] == vertics[2] || vertics[2] == vertics[0])return vertics[0];
	Line bi1(bisection(Line(vertics[0], vertics[1]), Line(vertics[0], vertics[2])));
	Line bi2(bisection(Line(vertics[1], vertics[2]), Line(vertics[1], vertics[0])));
	if (bi1[0] == bi2[0])return bi1[0];
	else {
		return is_ll(bi1, bi2);
	}
}

//???????????´?????????????????????
//???????????´??????????????§???????????¨????¢?????????¨?????????
vector<Point>  ex_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i < static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (abs(vertics[0] - vertics[1])<eps || abs(vertics[1] - vertics[2])<eps || (abs(vertics[2] - vertics[0])<eps))return vector<Point>();
	vector<Point>ecs;
	for (int i = 0; i < 3; ++i) {
		Line bi1(bisection(Line(vertics[i], vertics[i] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[i], vertics[(i + 1) % 3])));
		Line bi2(bisection(Line(vertics[(i + 1) % 3], vertics[(i + 1) % 3] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[(i + 1) % 3], vertics[i])));
		ecs.push_back(is_ll(bi1, bi2));
	}
	return ecs;
}


//a,b:??????
//c:????????§??????
//???????????´?????????????????¢?????????????±??????????
vector<Point>  same_dis(const vector<Line>&ls) {
	vector<Point>vertics;
	vertics.push_back(is_ll(ls[0], ls[2]));
	vertics.push_back(is_ll(ls[1], ls[2]));

	if (abs(vertics[0] - vertics[1]) < eps)return vector<Point>{vertics[0]};
	Line bis(bisection(ls[0], ls[1]));
	vector<Point>ecs;

	Line abi(bisection(Line(vertics[0], vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, abi));


	Line bbi(bisection(Line(vertics[0], 2.l*vertics[0] - vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, bbi));

	return ecs;
}
/* ??? */

// ?????¨????????????
vector<Point> is_cc(const Circle& c1, const Circle& c2) {
	vector<Point> res;
	ld d = abs(c1.p - c2.p);
	ld rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
	ld dfr = c1.r * c1.r - rc * rc;
	if (abs(dfr) < eps) dfr = 0.0;
	else if (dfr < 0.0) return res; // no intersection
	ld rs = sqrt(dfr);
	Point diff = (c2.p - c1.p) / d;
	res.push_back(c1.p + diff * Point(rc, rs));
	if (dfr != 0.0) res.push_back(c1.p + diff * Point(rc, -rs));
	return res;
}

//???????????????????????????
//  0 => out
//  1 => on
//  2 => in
int is_in_circle(const Circle &cir, const  Point& p) {
	ld dis = abs(cir.p - p);
	if (dis > cir.r + eps)return 0;
	else if (dis < cir.r - eps)return 2;
	else return 1;
}
//???lc??????rc??????????????????
//  0 => out
//  1 => on
//  2 => in
int circle_in_circle(const Circle &lc, const  Circle&rc) {
	ld dis = abs(lc.p - rc.p);
	if (dis < rc.r - lc.r - eps)return 2;
	else if (dis>rc.r - lc.r + eps)return 0;
	else return 1;
}

// ?????¨??´????????????
vector<Point> is_lc(const Circle& c, const Line& l) {
	vector<Point> res;
	ld d = dist_lp(l, c.p);
	if (d < c.r + eps) {
		ld len = (d > c.r) ? 0.0 : sqrt(c.r * c.r - d * d); //safety;
		Point nor = (l.a - l.b) / abs(l.a - l.b);
		res.push_back(proj(l, c.p) + len * nor);
		res.push_back(proj(l, c.p) - len * nor);
	}
	return res;
}

// ?????¨??????????????¢
vector<Point> is_sc(const Circle& c, const Line& l) {
	vector<Point> v = is_lc(c, l), res;
	for (Point p : v)
		if (isis_sp(l, p)) res.push_back(p);
	return res;
}

// ?????¨????????\???
vector<Line> tangent_cp(const Circle& c, const Point& p) {
	vector<Line> ret;
	Point v = c.p - p;
	ld d = abs(v);
	ld l = sqrt(norm(v) - c.r * c.r);
	if (isnan(l)) { return ret; }
	Point v1 = v * Point(l / d, c.r / d);
	Point v2 = v * Point(l / d, -c.r / d);
	ret.push_back(Line(p, p + v1));
	if (l < eps) return ret;
	ret.push_back(Line(p, p + v2));
	return ret;
}

// ?????¨????????\???
vector<Line> tangent_cc(const Circle& c1, const Circle& c2) {
	vector<Line> ret;
	if (abs(c1.p - c2.p) - (c1.r + c2.r) > -eps) {
		Point center = (c1.p * c2.r + c2.p * c1.r) / (c1.r + c2.r);
		ret = tangent_cp(c1, center);
	}
	if (abs(c1.r - c2.r) > eps) {
		Point out = (-c1.p * c2.r + c2.p * c1.r) / (c1.r - c2.r);
		vector<Line> nret = tangent_cp(c1, out);
		ret.insert(ret.end(), ALL(nret));
	}
	else {
		Point v = c2.p - c1.p;
		v /= abs(v);
		Point q1 = c1.p + v * Point(0, 1) * c1.r;
		Point q2 = c1.p + v * Point(0, -1) * c1.r;
		ret.push_back(Line(q1, q1 + v));
		ret.push_back(Line(q2, q2 + v));
	}
	return ret;
}
//??????????????????????????¢???
ld two_circle_area(const Circle&l, const Circle&r) {
	ld dis = abs(l.p - r.p);
	if (dis > l.r + r.r)return 0;
	else if (dis + r.r < l.r) {
		return r.r*r.r*pi;
	}
	else if (dis + l.r < r.r) {
		return l.r*l.r*pi;
	}
	else {
		ld ans = (l.r)*(l.r)*acos((dis*dis + l.r*l.r - r.r*r.r) / (2 * dis*l.r)) +
			(r.r)*(r.r)*acos((dis*dis + r.r*r.r - l.r*l.r) / (2 * dis*r.r)) -
			sqrt(4 * dis*dis*l.r*l.r - (dis*dis + l.r*l.r - r.r*r.r)*(dis*dis + l.r*l.r - r.r*r.r)) / 2;
		return ans;
	}

}

/* ????§???¢ */

typedef vector<Point> Polygon;

// ??¢???
ld area(const Polygon &p) {
	ld res = 0;
	int n = p.size();
	REP(j, n) res += cross(p[j], p[(j + 1) % n]);
	return res / 2;
}

// ????§???¢????????¢??????
bool is_counter_clockwise(const Polygon &poly) {
	ld angle = 0;
	int n = poly.size();
	REP(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n], c = poly[(i + 2) % n];
		angle += arg((c - b) / (b - a));
	}
	return angle > eps;
}

// ??????????????????
//  0 => out
//  1 => on
//  2 => in
int is_in_polygon(const Polygon &poly, const  Point& p) {
	ld angle = 0;
	int n = poly.size();
	REP(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n];
		if (isis_sp(Line(a, b), p)) return 1;
		angle += arg((b - p) / (a - p));
	}
	return eq(angle, 0) ? 0 : 2;
}
//??????????????????2?????????
enum { OUT, ON, IN };
int convex_contains(const Polygon &P, const Point &p) {
	const int n = P.size();
	Point g = (P[0] + P[n / 3] + P[2 * n / 3]) / 3.0l; // inner-point
	int a = 0, b = n;
	while (a + 1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (cross(P[a] - g, P[c] - g) > 0) { // angle < 180 deg
			if (cross(P[a] - g, p - g) > 0 && cross(P[c] - g, p - g) < 0) b = c;
			else                                                  a = c;
		}
		else {
			if (cross(P[a] - g, p - g) < 0 && cross(P[c] - g, p - g) > 0) a = c;
			else                                                  b = c;
		}
	}
	b %= n;
	if (cross(P[a] - p, P[b] - p) < 0) return 0;
	if (cross(P[a] - p, P[b] - p) > 0) return 2;
	return 1;
}

// ??????
// ???????????????????????¨????????????????????§??¨???
Polygon convex_hull(vector<Point> ps) {
	int n = ps.size();
	int k = 0;
	sort(ps.begin(), ps.end());
	Polygon ch(2 * n);
	for (int i = 0; i < n; ch[k++] = ps[i++])
		while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--])
		while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	ch.resize(k - 1);
	return ch;
}



// ????????????
vector<Polygon> convex_cut(const Polygon &ps, const Line& l) {
	int n = ps.size();
	Polygon Q;
	Polygon R;
	REP(i, n) {
		Point A = ps[i], B = ps[(i + 1) % n];
		Line m = Line(A, B);
		if (ccw(l.a, l.b, A) != -1) Q.push_back(A);
		if (ccw(l.a, l.b, A) != 1) R.push_back(A);
		if (ccw(l.a, l.b, A) * ccw(l.a, l.b, B) < 0 && isis_ll(l, m)) {
			Q.push_back(is_ll(l, m));
			R.push_back(is_ll(l, m));
		}
	}
	const vector<Polygon>polys{ Q,R };
	return polys;
}


/* ??¢??¬??????????????? */
void add_point(vector<Point> &ps, const Point p) {
	for (Point q : ps) if (abs(q - p) < eps) return;
	ps.push_back(p);
}

typedef ld Weight;
struct Edge {
	int src, dst;
	Weight weight;
	Edge(int src, int dst, Weight weight) :
		src(src), dst(dst), weight(weight) { }
};

typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

void add_edge(Graph &g, const int from, const int to, const Weight weight) {
	g[from].push_back(Edge{ from, to, weight });
}

pair<vector<Point>,Graph> segment_arrangement(const vector<Line> &s, const vector<Point> &p) {
	int n = p.size(), m = s.size();
	Graph g(n);
	REP(i, m) {
		vector<pair<ld, int>> vec;
		REP(j, n) if (isis_sp(s[i], p[j]))
			vec.emplace_back(abs(s[i].a - p[j]), j);
		sort(ALL(vec));
		REP(j, vec.size() - 1) {
			int from = vec[j].second, to = vec[j + 1].second;
			add_edge(g, from, to, static_cast<Weight>(abs(p[from] - p[to])));
			add_edge(g, to,from, static_cast<Weight>(abs(p[from] - p[to])));
		}
	}
	auto a(make_pair(p, g));
	return a;
}
pair<vector<Point>, Graph> sennbunn_arrangement(const vector<Line>&s) {
	vector<Point>crss;
	for (int i = 0; i < static_cast<int>(s.size()); ++i) {
		for (int j = i + 1; j < static_cast<int>(s.size()); ++j) {
			if (isis_ss(s[i], s[j])) {
				crss.push_back(is_ll2(s[i], s[j])[0]);
			}
		}
	}
	for (int i = 0; i <static_cast<int>(s.size()); ++i) {
		crss.push_back(s[i][0]);
		crss.push_back(s[i][1]);
	}
	sort(crss.begin(), crss.end());
	crss.erase(unique(crss.begin(), crss.end()), crss.end());
	return segment_arrangement(s, crss);
}


pair<bool, vector<Weight>> spfa(const int v_num, const vector<vector<Edge>>&es, const int start) {
	vector<Weight>diss(v_num, INT_MAX);
	queue<int>que;
	vector<bool>use(v_num);
	vector<int>count(v_num);
	que.emplace(start);
	diss[start] = 0;
	while (!que.empty()) {
		int src(que.front());
		que.pop();
		use[src] = false;
		for (auto e : es[src]) {
			const int d = e.dst;
			if (diss[src] + e.weight < diss[d]) {
				diss[d] = diss[src] + e.weight;
				if (!use[d]) {
					use[d] = true;
					count[d]++;
					if (count[d] >= v_num)return make_pair(false, vector<Weight>());
					que.emplace(d);
				}
			}
		}
	}
	return make_pair(true, diss);
}
struct aa {
	int now;
	ld time;
};
class Compare {
public:
	//aa?????????????????¶
	bool operator()(const aa&l, const aa&r) {
		return l.time> r.time;
	}
};
int main() {
	while (1) {
		int N; cin >> N;
		if (!N)break;
		int xs, ys, xg, yg; cin >> xs >> ys >> xg >> yg;
		vector<Line>ls;
		Point start(xs, ys), goal(xg, yg);
		for (int i = 0; i < N; ++i) {
			int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2;
			ls.emplace_back(Point(x1, y1), Point(x2, y2));
		}
		vector<Line>roads;
		vector<Line>signs;
		for (int i = 0; i < N; ++i) {
			int touchnum = 0;
			for (int j = 0; j < 2; ++j) {
				Point p(ls[i][j]);
				bool touch = false;
				for (int k = 0; k < N; ++k) {
					if (i == k)continue;
					else {
						if (isis_sp(ls[k],p))touch = true;
					}
				}
				if (touch)touchnum++;
			}
			if (touchnum == 2)roads.emplace_back(ls[i]);
			else signs.emplace_back(ls[i]);
		}
		auto pa(sennbunn_arrangement(roads));
		Graph g(pa.second);
		vector<Point>ps(pa.first);
		int startid, goalid;
		for (int i = 0; i < ps.size();++i){
			Point p(ps[i]);
			if (p == start)startid = i;
			else if (p == goal)goalid = i;
		}
		for (auto& es :g){
			for (auto& e : es) {
				Line l(ps[e.src],ps[e.dst]);
				for (int k = 0; k < signs.size(); ++k) {
					Line si(signs[k]);
					if (isis_ss(l, si)) {
						if (isis_sp(l, si[1]))swap(si.a, si.b);
						ld theta = (dot(l[1] - l[0], si[1] - si[0]));
						if (theta > -eps) {
							e.weight = 1e18;
						}
					}
				}
					
				
			}
		}
		vector<ld>times(g.size(),1e18);
		vector<vector<int>>memos(g.size());
		memos[startid].push_back(startid);
		priority_queue<aa,vector<aa>,Compare>que;
		times[startid] = 0;
		que.push(aa{ startid,0 });
		while (!que.empty()) {
			aa atop(que.top());
			que.pop();
			if (atop.now == goalid)break;
			for (auto e : g[atop.now]) {
				if (times[e.dst] > atop.time + e.weight) {
					times[e.dst] = atop.time + e.weight;
					memos[e.dst] = memos[e.src];
					memos[e.dst].emplace_back(e.dst);
					que.push(aa{ e.dst,atop.time + e.weight });
				}
			}
		}
		if (memos[goalid].empty()) {
			cout << -1 << endl;
		}
		else {

			for (auto m : memos[goalid]) {
				int x = int((ps[m].real()+eps));
				int y =int(ps[m].imag()+eps);
				cout << x << " " << y << endl;
			}
			cout << 0 << endl;
		}
	}
	return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 3300
final_rank: 17

code_snippet: #include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<string>
#include<stack>
#include<cstdio>
#include<cmath>
using namespace std;

typedef long long ll;
typedef double ld;
typedef pair<short,short> P;
typedef pair<ll,P> P1;

#define fr first
#define sc second
#define mp make_pair
#define pb push_back
#define rep(i,x) for(int i=0;i<x;i++)
#define rep1(i,x) for(int i=1;i<=x;i++)
#define rrep(i,x) for(int i=x-1;i>=0;i--)
#define rrep1(i,x) for(int i=x;i>0;i--)
#define sor(v) sort(v.begin(),v.end())
#define rev(s) reverse(s.begin(),s.end())
#define lb(vec,a) lower_bound(vec.begin(),vec.end(),a)
#define ub(vec,a) upper_bound(vec.begin(),vec.end(),a)
#define uniq(vec) vec.erase(unique(vec.begin(),vec.end()),vec.end())
#define mp1(a,b,c) P1(a,P(b,c))

const int INF=1000000000;
const int dir_4[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
const int dir_8[8][2]={{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1}};

int gcd(int x,int y){
	if(y == 0)return x;
	return gcd(y,x%y);
}

vector<P> dir[1002][1002];
int f(int x,int y,int dx,int dy){
	int ret = 0;
	rep(i,dir[x][y].size()){
		P p = dir[x][y][i];
		int t = (p.fr-x)*dx + (p.sc-y)*dy;
		if(t > 0)ret |= 1;
		else if(t == 0)ret |= 3;
		else ret |= 2;
	}
	return ret;
}

ld cul_dist(ld x1,ld y1,ld x2,ld y2){
	return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
		static int n;
		static int xs,ys,xg,yg;
		static short cnt[1002][1002];
		static vector<P> G[1002][1002];
		static bool used[1002][1002];
		static double dist[1002][1002];
		static P pre[1002][1002];
		priority_queue<pair<ld,P>,vector<pair<ld,P>>,greater<pair<ld,P>>> que;
int main(){
	while(1){
		static int x1[202],y1[202],x2[202],y2[202];
		scanf("%d",&n); if(n == 0)break;
		scanf("%d%d%d%d",&xs,&ys,&xg,&yg);
		rep(i,n){
			scanf("%d%d%d%d",&x1[i],&y1[i],&x2[i],&y2[i]);
		}
		
		rep(i,1002)rep(j,1002)cnt[i][j] = 0;
		rep(i,n){
			if(x1[i] > x2[i] || (x1[i] == x2[i] && y1[i] > y2[i])){
				swap(x1[i],x2[i]);
				swap(y1[i],y2[i]);
			}
			cnt[x1[i]][y1[i]] ++;
			cnt[x2[i]][y2[i]] ++;
		}
		
		rep(i,n){
			int dx = x2[i]-x1[i];
			int dy = y2[i]-y1[i];
			int g = gcd(abs(dx),abs(dy));
			dx /= g; dy /= g;
			int locx = x1[i]+dx , locy = y1[i]+dy;
			while(!(locx == x2[i] && locy == y2[i])){
				cnt[locx][locy] ++;
				locx += dx; locy += dy;
			}
		}
		
		rep(i,1002)rep(j,1002)dir[i][j].clear();
		rep(i,n){
			if(cnt[x1[i]][y1[i]] == 1){
				dir[x2[i]][y2[i]].pb(P(x1[i],y1[i]));
			}
			else if(cnt[x2[i]][y2[i]] == 1){
				dir[x1[i]][y1[i]].pb(P(x2[i],y2[i]));
			}
		}
		
		rep(i,1002)rep(j,1002)G[i][j].clear();
		rep(i,n){
			if(cnt[x1[i]][y1[i]] == 1 || cnt[x2[i]][y2[i]] == 1)continue;
			int dx = x2[i]-x1[i];
			int dy = y2[i]-y1[i];
			int g = gcd(abs(dx),abs(dy));
			dx /= g; dy /= g;
			int prex1 = -1 , prey1 = -1;
			int prex2 = -1 , prey2 = -1;
			int locx = x1[i] , locy = y1[i];
			while(locx <= x2[i] && !(dx == 0 && locy > y2[i])){
				if(cnt[locx][locy] >= 1){
					int t = f(locx,locy,dx,dy);
					if((t&1) == 0){
						if(prex1 != -1)G[prex1][prey1].pb(P(locx,locy));
						prex1 = locx; prey1 = locy;
					}
					else { prex1 = -1; prey1 = -1; }
					if((t&2) == 0){
						if(prex2 != -1)G[locx][locy].pb(P(prex2,prey2));
						prex2 = locx; prey2 = locy;
					}
					else { prex2 = -1; prey2 = -1; }
				}
				locx += dx; locy += dy;
			}
		}
		
		rep(i,1002)rep(j,1002){
			used[i][j] = false;
			dist[i][j] = (ld)INF;
			pre[i][j] = P ( -1 , -1 );
		}
		dist[xs][ys] = 0.0;
		que.push ( pair<ld,P> ( 0.0 , P ( xs,ys ) ) );
		while(!que.empty()){
			pair<ld,P> p = que.top(); que.pop();
			if(used[p.sc.fr][p.sc.sc])continue;
			used[p.sc.fr][p.sc.sc] = true;
			rep(i,G[p.sc.fr][p.sc.sc].size()){
				P to = G[p.sc.fr][p.sc.sc][i];
				if(dist[to.fr][to.sc] > dist[p.sc.fr][p.sc.sc] + cul_dist(p.sc.fr,p.sc.sc,to.fr,to.sc)){
					dist[to.fr][to.sc] = dist[p.sc.fr][p.sc.sc] + cul_dist(p.sc.fr,p.sc.sc,to.fr,to.sc);
					pre[to.fr][to.sc] = p.sc;
					que.push( pair<ld,P> ( dist[to.fr][to.sc] , to ) );
				}
			}
		}
		
		if(pre[xg][yg].fr == -1)cout << -1 << endl;
		else {
			vector<P> ans;
			P loc = P ( xg , yg );
			ans.pb(loc);
			while(loc != P(xs,ys)){
				loc = pre[loc.fr][loc.sc];
				ans.pb(loc);
			}
			rrep(i,ans.size()){
				if(!(cnt[ans[i].fr][ans[i].sc]-dir[ans[i].fr][ans[i].sc].size() == 1))printf("%d %d\n",ans[i].fr,ans[i].sc);
			}
			puts("0");
		}
	}
}
accuracy: 1
time_ms: 100
memory_kb: 63504
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;

typedef complex<double> P;

const double inf = 1e10;
const double eps = 1e-8;

bool equals(double a, double b) {
  return abs(a - b) < eps;
}

namespace std {
  bool operator < (const P &a, const P &b) {
    return ( a.real() != b.real()
             ? a.real() < b.real() : a.imag() < b.imag() );
  }
}

double dot(P a, P b) {
  return a.real()*b.real() + a.imag()*b.imag();
}

double cross(P a, P b) {
  return a.real()*b.imag() - a.imag()*b.real();
}

int ccw(P p, P a, P b) {
  a -= p;
  b -= p;
  if(cross(a, b) > eps) return 1;
  if(cross(a, b) < -eps) return -1;
  if(dot(a, b) < -eps) return 2;
  if(norm(a) + eps < norm(b)) return -2;
  return 0;
}

bool isIntersect(P a1, P a2, P b1, P b2) {
  return ( ccw(a1, a2, b1) * ccw(a1, a2, b2) <= 0 &&
           ccw(b1, b2, a1) * ccw(b1, b2, a2) <= 0 );
}

P getCrossP(P a1, P a2, P b1, P b2) {
  P a = a2 - a1;
  P b = b2 - b1;
  return a1 + a * cross(b, b1 - a1) / cross(b, a);
}

struct Edge { int v; double w; int rev; };
typedef vector<vector<Edge> > Graph;

Graph segmentArrangement(const vector<P> &s1, const vector<P> &s2,
                         vector<P> &ps) {
  int m = s1.size();
  for(int i = 0; i < m; ++i) {
    ps.push_back(s1[i]);
    ps.push_back(s2[i]);
    for(int j = i+1; j < m; ++j) {
      if(equals(cross(s1[i] - s2[i], s1[j] - s2[j]), 0.0)) continue;
      if(!isIntersect(s1[i], s2[i], s1[j], s2[j])) continue;
      ps.push_back(getCrossP(s1[i], s2[i], s1[j], s2[j]));
    }
  }
  sort(ps.begin(), ps.end());
  ps.erase(unique(ps.begin(), ps.end()), ps.end());

  int n = ps.size();
  Graph g(n);
  for(int i = 0; i< m; ++i) {
    vector<pair<double, int> > v;
    for(int j = 0; j < n; ++j) {
      if(ps[j] == s1[i] || ps[j] == s2[i] ||
         !ccw(s1[i], s2[i], ps[j])) {
        v.push_back(make_pair(norm(s1[i] - ps[j]), j));
      }
    }
    sort(v.begin(), v.end());
    for(int j = 0; j+1 < v.size(); ++j) {
      int a = v[j].second, b = v[j+1].second;
      double w = abs(ps[a] - ps[b]);
      g[a].push_back((Edge){b, w, g[b].size()});
      g[b].push_back((Edge){a, w, g[a].size()-1});
    }
  }
  return g;
}

typedef pair<double, int> Pair;

int n;
P s, g;
vector<P> s1, s2, ps;
vector<int> isSign;
int N, src, dst;
Graph G;

int main() {
  while(cin >> n && n) {
    cin >> s.real() >> s.imag();
    cin >> g.real() >> g.imag();
    s1.resize(n);
    s2.resize(n);
    for(int i = 0; i < n; ++i) {
      cin >> s1[i].real() >> s1[i].imag()
          >> s2[i].real() >> s2[i].imag();
    }

    ps.clear();
    G = segmentArrangement(s1, s2, ps);
    N = G.size();
    src = find(ps.begin(), ps.end(), s) - ps.begin();
    dst = find(ps.begin(), ps.end(), g) - ps.begin();

    isSign = vector<int>(ps.size());
    for(int i = 0; i < N; ++i) {
      if(G[i].size() == 1) {
        int a = i;
        int b = G[a][0].v;
        isSign[b] = true;
        int pc = 0;
        int c = G[b][pc].v;
        while(G[c].size() == 1) c = G[b][++pc].v;
        int pd = G[b].size()-1;
        int d = G[b][pd].v;
        while(G[d].size() == 1) d = G[b][--pd].v;
        double s = dot(ps[a] - ps[b], ps[c] - ps[b]);
        if(s >= 0.0) G[b][pc].w = inf;
        if(s <= 0.0) G[b][pd].w = inf;
        G[b][G[a][0].rev].w = inf;
      }
    }

    vector<double> cost(N, inf);
    priority_queue<Pair, vector<Pair>, greater<Pair> > que;
    vector<int> prev(N, -1);
    cost[src] = 0.0;
    que.push(make_pair(0.0, src));
    while(que.size()) {
      const Pair s = que.top(); que.pop();
      if(cost[s.second] < s.first) continue;
      if(s.second == dst) break;
      for(int i = 0; i < G[s.second].size(); ++i) {
        if(G[s.second][i].w == inf) continue;
        const Pair t(s.first + G[s.second][i].w, G[s.second][i].v);
        if(cost[t.second] <= t.first) continue;
        cost[t.second] = t.first;
        prev[t.second] = s.second;
        que.push(t);
      }
    }

    if(cost[dst] == inf) {
      cout << -1 << endl;
    } else {
      vector<int> vs;
      for(int v = dst; v != -1; v = prev[v]) {
        vs.push_back(v);
      }
      for(int i = vs.size()-1; i >= 0; --i) {
        if(isSign[vs[i]]) continue;
        cout << (int)ps[vs[i]].real() << " " 
             << (int)ps[vs[i]].imag() << endl;
      }
      cout << 0 << endl;
    }
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 1364
final_rank: 2

code_snippet: #include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <map>
#include <set>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <sstream>
#include <complex>
#include <stack>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iterator>
#include <bitset>

#define cauto const auto&

using namespace std;


namespace{
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

typedef vector<int> vint;
typedef vector<vector<int> > vvint;
typedef vector<long long> vll, vLL;
typedef vector<vector<long long> > vvll, vvLL;

#define VV(T) vector<vector< T > >

template <class T>
void initvv(vector<vector<T> > &v, int a, int b, const T &t = T()){
    v.assign(a, vector<T>(b, t));
}

template <class F, class T>
void convert(const F &f, T &t){
    stringstream ss;
    ss << f;
    ss >> t;
}


#define reep(i,a,b) for(int i=(a);i<(b);++i)
#define rep(i,n) reep((i),0,(n))
#define ALL(v) (v).begin(),(v).end()
#define PB push_back
#define fi first
#define se second
#define mkp make_pair
#define RALL(v) (v).rbegin(),(v).rend()

#define MOD 1000000007LL
typedef pair<double,double> pdd;
const double EPS = 1e-8;
const double INF = 1e12;
const double PI = asin(0.5)*6;
typedef complex<double> P;

#define X real()
#define Y imag()

#define Curr(P,i) P[(i)%P.size()]
#define Next(P,i) P[(i+1)%P.size()]
#define Prev(P,i) P[(i+P.size()-1)%P.size()]

namespace std{
  bool operator<(const P a,const P b){
    return a.X != b.X ? a.X < b.X : a.Y < b.Y;
  }
}
double cross(const P a,const P b){
  return (conj(a)*b).imag();
}
double dot(const P a,const P b){
  return (conj(a)*b).real();
}
int ccw(P a,P b,P c){
  b-=a;
  c-=a;
}

struct L : public vector<P>{
  L(const P a,const P b){
    push_back(a),push_back(b);
  }
};
typedef L S;
bool isCrossSP(S a,P p){
  return abs(a[0]-p)+abs(a[1]-p)-abs(a[0]-a[1]) < EPS;
}
pdd ptopdd(P a){
	return pdd(a.real(),a.imag());
}
P pddtop(pdd a){
	return P(a.first,a.second);
}
int foo3(S a,P b,P c){
	double ab0=abs(a[0]-b);
	double ac0=abs(a[0]-c);
	double bc =abs(b-c);
	if(abs(ac0*ac0-ab0*ab0-bc*bc)<EPS){
		return 2;
	}
	if(ac0*ac0-ab0*ab0-bc*bc>EPS){
		return 0;
	}
	return 1;
}
bool operator<(P a,P b){
	if(a.X==b.X){
		return a.Y<b.Y;
	}
	return a.X<b.X;
}
void mainmain(){
	int n;
	while(cin>>n,n){
		P s,g;
		double a[4];
		rep(i,4) cin>>a[i];
		s=P(a[0],a[1]);
		g=P(a[2],a[3]);
		vector<S> v1;
		S tmp(s,g);
		rep(i,n){
			double a[4];
			rep(j,4) cin>>a[j];
			P t1=P(a[0],a[1]);
			P t2=P(a[2],a[3]);
			S tmp=S(t1,t2);
			v1.PB(tmp);
		}
		vector<S> sign,road;
		rep(i,n){
			bool f1=true;
			bool f2=true;
			rep(j,n){
				if(i==j) continue;
				if(isCrossSP(v1[j],v1[i][0])){
					f1=false;
				}
				if(isCrossSP(v1[j],v1[i][1])){
					f2=false;
				}
			}
			if(f1||f2){
				sign.PB(v1[i]);
			}
			else{
				road.PB(v1[i]);
			}
		}
		vector<S> troad;
		rep(i,road.size()){
			vector<S> tmp;
			tmp.PB(road[i]);
			rep(j,road.size()){
				if(i==j) continue;
				rep(k,tmp.size()){
					bool f=false;
					P p;
					rep(o,2){
						if(isCrossSP(tmp[k],road[j][o])){
							f=true;
							p=road[j][o];
						}
					}
					if(f&&abs(tmp[k][0]-p)>EPS&&abs(tmp[k][1]-p)>EPS){
						S tt=tmp[k];
						tmp[k]=S(tt[0],p);
						tmp.PB(S(tt[1],p));
						k--;
					}
				}
			}
			rep(j,tmp.size()){
				troad.PB(tmp[j]);
			}
		}
		road=troad;
		map<pdd,int> ma;
		vector<pii> vp;
		rep(i,road.size()){
			rep(j,2){
				pdd t=ptopdd(road[i][j]);
				if(ma.find(t)==ma.end()){
					ma[t]=0;
					vp.PB(pii(int(t.fi),int(t.se)));
					ma[t]=ma.size()-1;
				}
			}
		}
		typedef pair<int,double> pid;
		VV(pid) vv(ma.size());
		rep(i,road.size()){
			bool f[2]={true,true};
			rep(j,sign.size()){
				rep(k,2){
					if(isCrossSP(road[i],sign[j][k])){
						int aa=foo3(road[i],sign[j][k],sign[j][1-k]);
						if(aa==2){
							f[0]=f[1]=false;
						}
						if(aa==0){
							f[0]=false;
						}
						if(aa==1){
							f[1]=false;
						}
					}
				}
			}
			rep(j,2){
				if(f[j]){
					vv[ma[ptopdd(road[i][j])]].PB(pid(ma[ptopdd(road[i][1-j])],abs(road[i][0]-road[i][1])));
				}
			}
		}
		priority_queue<pair<double,pii> > pq;
		vector<pair<double,int> > ans(vp.size(),pair<double,int>(INF,-2));
		pq.push(pair<double,pii>(0.0,pii(ma[ptopdd(s)],-1)));
		while(!pq.empty()){
			pair<double,pii> top=pq.top();
			pq.pop();
			if(ans[top.se.fi].se!=-2) continue;
			ans[top.se.fi]=pair<double,int>(top.fi,top.se.se);
			rep(i,vv[top.se.fi].size()){
				if(ans[vv[top.se.fi][i].fi].se!=-2) continue;
				pq.push(pair<double,pii>(top.fi-vv[top.se.fi][i].se,pii(vv[top.se.fi][i].fi,top.se.fi)));
			}
		}
		vector<int> res;
		int pos=ma[ptopdd(g)];
		if(ans[pos].se==-2){
			cout<<-1<<endl;
			continue;
		}
		while(pos!=-1){
			res.PB(pos);
			pos=ans[pos].se;
		}
		reverse(ALL(res));
		rep(i,res.size()){
			cout<<vp[res[i]].fi<<" "<<vp[res[i]].se<<endl;
		}
		cout<<0<<endl;
	}
}



}
main() try{
    mainmain();
}
catch(...){
}
accuracy: 1
time_ms: 60
memory_kb: 1348
final_rank: 15

code_snippet: #include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <map>
//#include <utility>
#include <set>
#include <iostream>
//#include <memory>
#include <string>
#include <vector>
#include <algorithm>
//#include <functional>
#include <sstream>
//#include <deque>
#include <complex>
#include <stack>
#include <queue>
#include <cstdio>
//#include <cctype>
#include <cstring>
//#include <ctime>
#include <iterator>
#include <bitset>
//#include <numeric>
//#include <list>
//#include <iomanip>

#if __cplusplus >= 201103L
#include <array>
#include <tuple>
#include <initializer_list>
#include <unordered_set>
#include <unordered_map>
#include <forward_list>

#define cauto const auto&
#else

#endif

using namespace std;


namespace{
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

typedef vector<int> vint;
typedef vector<vector<int> > vvint;
typedef vector<long long> vll, vLL;
typedef vector<vector<long long> > vvll, vvLL;

#define VV(T) vector<vector< T > >

template <class T>
void initvv(vector<vector<T> > &v, int a, int b, const T &t = T()){
    v.assign(a, vector<T>(b, t));
}

template <class F, class T>
void convert(const F &f, T &t){
    stringstream ss;
    ss << f;
    ss >> t;
}


#define reep(i,a,b) for(int i=(a);i<(b);++i)
#define rep(i,n) reep((i),0,(n))
#define ALL(v) (v).begin(),(v).end()
#define PB push_back
#define fi first
#define se second
#define mkp make_pair
#define RALL(v) (v).rbegin(),(v).rend()

#define MOD 1000000007LL
// #define EPS 1e-8
// static const int INF=1<<24;
typedef pair<double,double> pdd;
const double EPS = 1e-8;
const double INF = 1e12;
const double PI = asin(0.5)*6;
typedef complex<double> P;

#define X real()
#define Y imag()

#define Curr(P,i) P[(i)%P.size()]
#define Next(P,i) P[(i+1)%P.size()]
#define Prev(P,i) P[(i+P.size()-1)%P.size()]

namespace std{
  bool operator<(const P a,const P b){
    return a.X != b.X ? a.X < b.X : a.Y < b.Y;
  }
}
//gaiseki
double cross(const P a,const P b){
  return (conj(a)*b).imag();
}
//naiseki
double dot(const P a,const P b){
  return (conj(a)*b).real();
}
// TODO make graph (20)
int ccw(P a,P b,P c){
  b-=a;
  c-=a;
  if(cross(b,c)>0)    return +1;//counter clockwise
  if(cross(b,c)<0)    return -1;//clockwise
  if(dot(b,c)<0)      return +2;// c--a--b
  if(norm(b)<norm(c)) return -2;// a--b--c
                      return  0;// a--c--b(or b==c)
}

struct L : public vector<P>{
  L(const P a,const P b){
    push_back(a),push_back(b);
  }
};
typedef L S;
bool isCrossSP(S a,P p){
  return abs(a[0]-p)+abs(a[1]-p)-abs(a[0]-a[1]) < EPS;
}
pdd ptopdd(P a){
	return pdd(a.real(),a.imag());
}
P pddtop(pdd a){
	return P(a.first,a.second);
}
int foo3(S a,P b,P c){
	double ab0=abs(a[0]-b);
	double ac0=abs(a[0]-c);
	double bc =abs(b-c);
	double t=ac0*ac0-ab0*ab0-bc*bc;
	if(abs(ac0*ac0-ab0*ab0-bc*bc)<EPS){
		return 2;
	}
	if(ac0*ac0-ab0*ab0-bc*bc>EPS){
		return 0;
	}
	return 1;
}
bool operator<(P a,P b){
	if(a.X==b.X){
		return a.Y<b.Y;
	}
	return a.X<b.X;
}
void mainmain(){
	int n;
	while(cin>>n,n){
		P s,g;
		double a[4];
		rep(i,4) cin>>a[i];
		s=P(a[0],a[1]);
		g=P(a[2],a[3]);
		vector<S> v1;
		S tmp(s,g);
		rep(i,n){
			double a[4];
			rep(j,4) cin>>a[j];
			P t1=P(a[0],a[1]);
			P t2=P(a[2],a[3]);
			S tmp=S(t1,t2);
			v1.PB(tmp);
		}
		vector<S> sign,road;
		rep(i,n){
			bool f1=true;
			bool f2=true;
			rep(j,n){
				if(i==j) continue;
				if(isCrossSP(v1[j],v1[i][0])){
					f1=false;
				}
				if(isCrossSP(v1[j],v1[i][1])){
					f2=false;
				}
			}
			if(f1||f2){
				sign.PB(v1[i]);
			}
			else{
				road.PB(v1[i]);
			}
		}
		vector<S> troad;
		rep(i,road.size()){
			vector<S> tmp;
			tmp.PB(road[i]);
			rep(j,road.size()){
				if(i==j) continue;
				rep(k,tmp.size()){
					bool f=false;
					P p;
					rep(o,2){
						if(isCrossSP(tmp[k],road[j][o])){
							f=true;
							p=road[j][o];
						}
					}
					if(f&&abs(tmp[k][0]-p)>EPS&&abs(tmp[k][1]-p)>EPS){
						S tt=tmp[k];
						tmp[k]=S(tt[0],p);
						tmp.PB(S(tt[1],p));
						k--;
					}
				}
			}
			rep(j,tmp.size()){
				troad.PB(tmp[j]);
			}
		}
		road=troad;
		map<pdd,int> ma;
		vector<pii> vp;
		rep(i,road.size()){
			rep(j,2){
				pdd t=ptopdd(road[i][j]);
				if(ma.find(t)==ma.end()){
					ma[t]=0;
					vp.PB(pii(int(t.fi),int(t.se)));
					ma[t]=ma.size()-1;
				}
			}
		}
		typedef pair<int,double> pid;
		VV(pid) vv(ma.size());
		rep(i,road.size()){
			bool f[2]={true,true};
			rep(j,sign.size()){
				rep(k,2){
					if(isCrossSP(road[i],sign[j][k])){
						int aa=foo3(road[i],sign[j][k],sign[j][1-k]);
						if(aa==2){
							f[0]=f[1]=false;
						}
						if(aa==0){
							f[0]=false;
						}
						if(aa==1){
							f[1]=false;
						}
					}
				}
			}
			rep(j,2){
				if(f[j]){
					vv[ma[ptopdd(road[i][j])]].PB(pid(ma[ptopdd(road[i][1-j])],abs(road[i][0]-road[i][1])));
				}
			}
		}
		priority_queue<pair<double,pii> > pq;
		vector<pair<double,int> > ans(vp.size(),pair<double,int>(INF,-2));
		pq.push(pair<double,pii>(0.0,pii(ma[ptopdd(s)],-1)));
		while(!pq.empty()){
			pair<double,pii> top=pq.top();
			pq.pop();
			if(ans[top.se.fi].se!=-2) continue;
			// cout<<top.se.fi<<endl;
			// cout<<"size "<<vv[top.se.fi].size()<<endl;
			// cout<<top.fi<<" "<<top.se.fi<<" "<<top.se.se<<endl;
			ans[top.se.fi]=pair<double,int>(top.fi,top.se.se);
			rep(i,vv[top.se.fi].size()){
				if(ans[vv[top.se.fi][i].fi].se!=-2) continue;
				pq.push(pair<double,pii>(top.fi-vv[top.se.fi][i].se,pii(vv[top.se.fi][i].fi,top.se.fi)));
			}
			// cout<<"hoge"<<endl;
		}
		// puts("hoge");
		vector<int> res;
		int pos=ma[ptopdd(g)];
		// rep(i,ans.size()){
			// cout<<i<<" "<<ans[i].fi<<" "<<ans[i].se<<endl;
		// }
		// continue;
		if(ans[pos].se==-2){
			cout<<-1<<endl;
			continue;
		}
		while(pos!=-1){
			// cout<<pos<<endl;
			res.PB(pos);
			pos=ans[pos].se;
		}
		// cout<<"vp "<<endl;
		// rep(i,vp.size()){
			// cout<<i<<" "<<vp[i].fi<<" "<<vp[i].se<<" "<<ans[i].fi<<endl;
		// }
		reverse(ALL(res));
		rep(i,res.size()){
			cout<<vp[res[i]].fi<<" "<<vp[res[i]].se<<endl;
		}
		cout<<0<<endl;
	}
}



}
main() try{
    mainmain();
}
catch(...){
}
/*
8
1 1
4 4
1 1 4 1
1 1 1 4
3 1 3 4
4 3 5 3
2 4 3 5
4 1 4 4
3 3 2 2
1 4 4 4
9
1 5
5 1
5 4 5 1
1 5 1 1
1 5 5 1
2 3 2 4
5 4 1 5
3 2 2 1
4 2 4 1
1 1 5 1
5 3 4 3
11
5 5
1 0
3 1 5 1
4 3 4 2
3 1 5 5
2 3 2 2
1 0 1 2
1 2 3 4
3 4 5 5
1 0 5 2
4 0 4 1
5 5 5 1
2 3 2 4
0
*/
/*
1 1
3 1
3 4
4 4
0
-1
5 5
5 2
3 1
1 0
0
*/
accuracy: 1
time_ms: 60
memory_kb: 1348
final_rank: 15

code_snippet: #include <iostream>
#include <utility>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;

#define x first
#define y second
#define fi first
#define se second
#define mkp make_pair

typedef pair<int,int> pii;

const int INF = 1e9;

int n;
pii s, g;
vector<pair<pii,pii> > lineseg, street, sign;

template<class T>
T sqr(T x) {
	return x * x;
}

double sqrdist(pii a, pii b) {
	return sqr(a.x-b.x) + sqr(a.y-b.y);
}

double dist(pii a, pii b) {
	return sqrt(sqr(a.x-b.x) + sqr(a.y-b.y));
}

int main() {
	while(cin >> n, n) {
		cin >> s.x >> s.y;
		cin >> g.x >> g.y;
		lineseg.clear();
		street.clear();
		sign.clear();
		for(int i = 0; i < n; i++) {
			pii a, b;
			cin >> a.x >> a.y >> b.x >> b.y;
			lineseg.push_back(mkp(a,b));
		}

		// street or sign.
		for(int i = 0; i < lineseg.size(); i++) {
			bool a, b;
			pair<pii,pii> c;
			a = b = true;
			c = lineseg[i];
			for(int j = 0; j < lineseg.size(); j++) {
				if(j != i) {
					pair<pii,pii> d;
					d = lineseg[j];
					if(fabs(dist(d.fi, c.fi) + dist(d.se, c.fi) - dist(d.fi, d.se)) < 1e-9)
						a = false;
					if(fabs(dist(d.fi, c.se) + dist(d.se, c.se) - dist(d.fi, d.se)) < 1e-9)
						b = false;
				}
			}
			if(a || b) {
				if(a)
					swap(c.fi, c.se);
				sign.push_back(c);
			}
			else
				street.push_back(c);
		}

		// make graph.
		// vertex
		map<pii, int> vertex;
		for(int i = 0; i < street.size(); i++) {
			if(vertex.find(street[i].fi) == vertex.end()) {
				vertex.insert(mkp(street[i].fi, vertex.size()));
			}
			if(vertex.find(street[i].se) == vertex.end()) {
				vertex.insert(mkp(street[i].se, vertex.size()));
			}
		}

		// edge
		double edge[512][512];
		double wf[512][512];
		for(int i = 0; i < 512; i++) {
			for(int j = 0; j < 512; j++) {
				edge[i][j] = INF;
				wf[i][j] = INF;
			}
			edge[i][i] = 0;
			wf[i][i] = 0;
		}
		
		vector<pair<pii,pii> > cut(street.begin(), street.end());
		for(int i = 0; i < cut.size(); i++) {
			pair<pii,pii> a, b;
			a = cut[i];
			for(int j = 0; j < cut.size(); j++) {
				b = cut[j];
				if((fabs(dist(a.fi, b.fi) + dist(a.se, b.fi) - dist(a.fi, a.se)) < 1e-9 && a.fi != b.fi && a.se != b.fi)){
					cut.erase(cut.begin()+i);
					cut.push_back(mkp(a.fi,b.fi));
					cut.push_back(mkp(b.fi,a.se));
					i--;
					break;
				}
				else if(fabs(dist(a.fi, b.se) + dist(a.se, b.se) - dist(a.fi, a.se)) < 1e-9 && a.fi != b.se && a.se != b.se) {
					cut.erase(cut.begin()+i);
					cut.push_back(mkp(a.fi,b.se));
					cut.push_back(mkp(b.se,a.se));
					i--;
					break;
				}
			}
		}

		for(int i = 0; i < cut.size(); i++) {
			pair<pii,pii> a, b;
			a = cut[i];
			bool f2s, s2f;
			f2s = s2f = true;
			for(int j = 0; j < sign.size(); j++) {
				b = sign[j];
				if(fabs(dist(a.fi, b.fi) + dist(a.se, b.fi) - dist(a.fi, a.se)) < 1e-9) {
					if(fabs(sqrdist(a.fi, b.fi) + sqrdist(b.fi, b.se) - sqrdist(a.fi, b.se)) < 1e-9) {
						f2s = s2f = false;
					}
					else if(sqrdist(a.fi, b.fi) + sqrdist(b.fi, b.se) - sqrdist(a.fi, b.se) > 0) {
						s2f = false;
					}
					else {
						f2s = false;
					}
				}
			}
			if(f2s) {
				edge[vertex[a.fi]][vertex[a.se]] = wf[vertex[a.fi]][vertex[a.se]] = dist(a.fi, a.se);
			}
			if(s2f) {
				edge[vertex[a.se]][vertex[a.fi]] = wf[vertex[a.se]][vertex[a.fi]] = dist(a.fi, a.se);
			}
		}

		// warshall floyd
		for(int i = 0; i < vertex.size(); i++) {
			for(int j = 0; j < vertex.size(); j++) {
				for(int k = 0; k < vertex.size(); k++) {
					wf[j][k] = min(wf[j][k], wf[j][i] + wf[i][k]);
				}
			}
		}

		double min_cost;
		min_cost = wf[vertex[s]][vertex[g]];

		if(fabs(min_cost - INF) < 1e-9)
			cout << -1 << endl;
		else {
			vector<int> path;
			int indx, indx_s;
			indx = vertex[g];
			indx_s = vertex[s];
			while(indx != indx_s) {
				int nex = -1;
				path.push_back(indx);
				for(int i = 0; i < vertex.size(); i++) {
					if(i != indx && fabs(wf[indx_s][i] + edge[i][indx] - wf[indx_s][indx]) < 1e-9)
						nex = i;
				}
				indx = nex;
			}
			path.push_back(indx_s);
			reverse(path.begin(), path.end());

			vector<pii> indx2pt;
			indx2pt.resize(vertex.size());
			for(map<pii,int>::iterator iter = vertex.begin(); iter != vertex.end(); iter++) {
				indx2pt[iter->se] = iter->fi;
			}

			for(int i = 0; i < path.size(); i++) {
				pii tmp = indx2pt[path[i]];
				cout << tmp.x << " " << tmp.se << endl;
			}
			cout << 0 << endl;
		}
	}
}
accuracy: 1
time_ms: 30
memory_kb: 5344
final_rank: 13

code_snippet: #include<cstdio>
#include<vector>
#include<string>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<complex>
#include<cmath>

using namespace std;

#define reps(i,f,n) for(int i=f;i<int(n);i++)
#define rep(i,n) reps(i,0,n)

#define X real()
#define Y imag()


const int INF = 1000000007;
const double EPS = 0.00001;
const int N = 222;
const int M = 444;

typedef pair<int,int> pii;


typedef complex<double> P;
class L:public vector<P>{
	public:
	L(P a, P b){
		push_back(a);
		push_back(b);
	}
	L(){
		push_back(P());
		push_back(P());
	}
};


double dot(P a, P b){return a.X*b.X + a.Y*b.Y;}
double cross(P a, P b){return a.X*b.Y - a.Y*b.X;}

double dist_LP(L a, P b){
	P e = a[1]-a[0];
	e = e/abs(e);
	
	double alen = abs(a[1]-a[0]);
	
	double d = dot(b-a[0], e);
	if(d<0 || d>=alen){
		return min(abs(b-a[0]), abs(b-a[1]));
	}
	
	double f = abs(b-a[0]);
	return sqrt(max(0.0, f*f - d*d));
}

int n;
P st,en;
vector<L> line;


bool input(){
	
	cin>>n;
	if(n==0)return false;
	
	double a,b,c,d;
	cin>>a>>b>>c>>d;
	st = P(a,b);
	en = P(c,d);
	
	line.clear();
	rep(i,n){
		cin>>a>>b>>c>>d;
		line.push_back(L(P(a,b), P(c,d)));
	}
	return true;
}


vector<L> road;
vector<L> sign;

void inputsplit(){
	road.clear();
	sign.clear();
	rep(i,line.size()){
		bool hita = false;
		bool hitb = false;
		rep(j,line.size()){
			if(i==j)continue;
			if(dist_LP(line[j], line[i][0]) < EPS)hita = true;
			if(dist_LP(line[j], line[i][1]) < EPS)hitb = true;
		}
		if(hita && hitb)road.push_back(line[i]);
		else sign.push_back(line[i]);
	}
}

void inputsplit2(){
	vector<vector<L> > copy;
	rep(i,road.size()){
		vector<L> ex(1);
		ex[0] = road[i];
		
		rep(j,road.size()){
			if(i==j)continue;
			rep(k,ex.size()){
				bool ok = false;
				P point(0,0);
				
				rep(p,2){
					double d = dist_LP(ex[k], road[j][p]);
					if(d<EPS){
						ok=true;
						point = road[j][p];
					}
				}
				if(ok && min(abs(ex[k][0]-point), abs(ex[k][1]-point))>EPS){
					L bef = ex[k];
					ex.erase(ex.begin()+k);
					k--;
					ex.push_back(L(bef[0], point));
					ex.push_back(L(bef[1], point));
				}
			}
		}
		copy.push_back(ex);
	}
	vector<L> res;
	rep(i,copy.size()){
		rep(j,copy[i].size())res.push_back(copy[i][j]);
	}
	road = res;
}

map<pii,int> table;
int tonum(P pos){
	pii p = pii( int(pos.X+0.5),  int(pos.Y+0.5) );
	if(table.find(p)==table.end()){
		table[p] = 0;
		table[p] = table.size()-1;
	}
	return table[p];
}
P topos(int num){
	for(map<pii,int>::iterator it = table.begin(); it!=table.end(); it++){
		if(it->second==num)return P(it->first.first, it->first.second);
	}
	return P(INF,INF);
}

void setroadnum(){
	rep(i,road.size()){
		tonum(road[i][0]);
		tonum(road[i][1]);
	}
}

double edge[M][M];
void setEdge(){
	rep(i,M)rep(j,M)edge[i][j]=INF;
	rep(i,M)edge[i][i]=0;
	
	rep(i,road.size()){
		int a = tonum(road[i][0]);
		int b = tonum(road[i][1]);
		double len = abs(road[i][1]-road[i][0]);
		edge[a][b] = edge[b][a] = len;
		
		rep(j,sign.size()){
			bool ok = false;
			bool rev = false;
			rep(k,2){
				if(dist_LP(road[i], sign[j][k])<EPS){
					ok = true;
					if(k==1)rev=true;
				}
			}
			
			if(ok){
				L s = sign[j];
				if(rev){
					swap(s[0], s[1]);
				}
				double dval = dot(road[i][1]-road[i][0], s[1]-s[0]);
				if(dval<EPS)edge[b][a] = INF;
				if(dval>-EPS) edge[a][b] = INF;
			}
		}
	}
}

double dp[M][M];
vector<P> wf(){
	rep(i,M)rep(j,M)dp[i][j] = edge[i][j];
	
	int m = table.size();
	rep(k,m)rep(i,m)rep(j,m)dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]);
	
	int stnum = tonum(st);
	int ennum = tonum(en);
	
	vector<P> ret;
	if(dp[stnum][ennum] > INF-EPS)return ret;
	
	ret.push_back(topos(ennum));
	while(1){
		if(ennum == stnum)break;
		rep(i,m){
			if(i==ennum)continue;
			double d = edge[i][ennum]-(dp[stnum][ennum]-dp[stnum][i]);
			if(abs(d)<EPS){
				ret.push_back(topos(i));
				ennum = i;
				break;
			}
		}
	}
	
	reverse(ret.begin(),ret.end());
	return ret;
}

vector<P> solve(){
	table.clear();
	inputsplit();
	inputsplit2();
	
	setroadnum();
	
	setEdge();
	vector<P> ret = wf();
	return ret;
}

void call(){
	vector<P> res = solve();
	if(res.size()==0)puts("-1");
	else{
		rep(i,res.size()){
			printf("%d %d\n",int(res[i].X+0.5), int(res[i].Y+0.5));
		}
		puts("0");
	}
}



int main(){
	while(input())call();
}
accuracy: 1
time_ms: 100
memory_kb: 4400
final_rank: 19

code_snippet: #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<sstream>
#include<string>
#include<vector>
#include<map>
#include<list>
#include<queue>
#include<deque>
#include<algorithm>
#include<numeric>
#include<utility>
#include<complex>
#include<functional>
 
using namespace std;

/* constant */

#define MAX_N	(200)
#define MAX_P	(MAX_N * 2)

#define T_SEG	(0)
#define T_SIGN	(1)

#define D_NONE	(0)
#define D_FWD	(1)
#define D_BWD	(2)
#define D_BOTH	(3)

#define INF	(1e10)

/* typedef */

typedef vector<int> vi;
typedef vector<long long> vl;
typedef vector<double> vd;
typedef pair<int,int> pii;
typedef pair<long,long> pll;
typedef long long ll;
typedef deque<int> di;

struct Pt {
  int x, y;

  Pt() {}
  Pt(int _x, int _y) { x = _x; y = _y; }

  bool operator==(Pt pt) { return x == pt.x && y == pt.y; }
  Pt operator+(Pt pt) { return Pt(x + pt.x, y + pt.y); }
  Pt operator-(Pt pt) { return Pt(x - pt.x, y - pt.y); }
  Pt operator-() { return Pt(-x, -y); }
  //Pt operator*(double t) { return Pt(x * t, y * t); }
  //Pt operator/(double t) { return Pt(x / t, y / t); }
  int dot(Pt v) { return x * v.x + y * v.y; }
  int cross(Pt v) { return x * v.y - y * v.x; }
  int dist2() { return x * x + y * y; }
  double dist() { return sqrt(dist2()); }

  string to_s() {
    stringstream ss;
    ss << "(" << x << "," << y << ")";
    return ss.str();
  }
};

struct Seg {
  Pt p0, p1;
  int i0, i1, type;

  string to_s() {
    stringstream ss;
    ss << p0.to_s() << "-" << p1.to_s();
    ss << "[" << i0 << "," << i1 << "," << type << "]";
    return ss.str();
  }
};

/* global variables */

Pt pts[MAX_P];
Seg segs[MAX_N];

vi psegs[MAX_P];
int ptypes[MAX_P];

double edges[MAX_P][MAX_P];
vi nbrs[MAX_P];

double dists[MAX_P];
int prevs[MAX_P];

/* classes */

class CompDist {
public:
  bool operator()(const int a, const int b) const {
    return (dists[b] < dists[a]);
  }
};

/* subroutines */

bool on_seg(Pt pt, Seg seg) {
  Pt v0 = seg.p0 - pt;
  Pt v1 = seg.p1 - pt;
  return ((seg.p1 - seg.p0).cross(v0) == 0 && v0.dot(v1) <= 0);
}

int pt_index(int npts, Pt *pts, Pt& pt) {
  Pt *pit = find(pts, pts + npts, pt);
  return ((pit == pts + npts) ? -1 : pit - pts);
}

/* main */

int main() {
  for (;;) {
    int n;
    cin >> n;
    if (n == 0) break;

    Pt st, gl;
    cin >> st.x >> st.y;
    cin >> gl.x >> gl.y;
    //cout << st.to_s() << gl.to_s() << endl;

    int npts = 0;
    
    for (int i = 0; i < n; i++) {
      Seg& seg = segs[i];
      cin >> seg.p0.x >> seg.p0.y >> seg.p1.x >> seg.p1.y;
      seg.type = T_SEG;
      //cout << seg.to_s() << endl;

      int pi0 = pt_index(npts, pts, seg.p0);
      if (pi0 < 0) {
	seg.i0 = npts;
	pts[npts++] = seg.p0;
      }
      else
	seg.i0 = pi0;
      
      int pi1 = pt_index(npts, pts, seg.p1);
      if (pi1 < 0) {
	seg.i1 = npts;
	pts[npts++] = seg.p1;
      }
      else
	seg.i1 = pi1;
    }
    //for (int i = 0; i < npts; i++) cout << pts[i].to_s(); cout << endl;
    //for (int i = 0; i < n; i++) cout << segs[i].to_s(); cout << endl;

    for (int i = 0; i < npts; i++) {
      psegs[i].clear();
      for (int j = 0; j < n; j++)
	if (on_seg(pts[i], segs[j])) {
	  //cout << pti.to_s() << " on " << segs[j].to_s() << endl;
	  psegs[i].push_back(j);
	}
    }
    //for (int i = 0; i < npts; i++) cout << psegs[i].size() << ' '; cout << endl;

    memset(ptypes, T_SEG, sizeof(ptypes));
    
    for (int i = 0; i < n; i++) {
      if (psegs[segs[i].i0].size() == 1 || psegs[segs[i].i1].size() == 1) {
	segs[i].type = T_SIGN;
	int i0 = segs[i].i0;
	int i1 = segs[i].i1;
	ptypes[i0] = ptypes[i1] = T_SIGN;
      }
    }
    //for (int i = 0; i < n; i++) cout << segs[i].to_s() << endl;

    for (int i = 0; i < npts; i++) {
      for (int j = 0; j < npts; j++) edges[i][j] = 0.0;
      nbrs[i].clear();
    }
    
    for (int i = 0; i < n; i++) {
      Seg& segi = segs[i];
      if (segi.type == T_SIGN) continue;

      Pt& p0 = segi.p0;
      Pt& p1 = segi.p1;
      Pt v01 = p1 - p0;

      vector<pii> spts;

      for (int j = 0; j < npts; j++) {
	vi& psj = psegs[j];
	if (find(psj.begin(), psj.end(), i) != psj.end()) {
	  pii paj((pts[j] - p0).dot(v01), j);
	  spts.push_back(paj);
	}
      }
      sort(spts.begin(), spts.end());

      //for (int j = 0; j < spts.size(); j++)
      //cout << "(" << spts[j].first << "," << spts[j].second << ")";
      //cout << endl;

      int prvj = spts[0].second;
      int direc = D_BOTH;

      for (int j = 1; j < spts.size(); j++) {
	int pj = spts[j].second;

	if (ptypes[pj] == T_SIGN) {
	  for (int k = 0; k < n; k++) {
	    Seg& segk = segs[k];
	    if (k != i && segk.type == T_SIGN &&
		(pj == segk.i0 || pj == segk.i1)) {
	      Pt vsign =
		(pj == segk.i0) ? segk.p1 - segk.p0 : segk.p0 - segk.p1;
	      int dot = vsign.dot(v01);
	      if (dot >= 0) direc &= ~D_FWD;
	      if (dot <= 0) direc &= ~D_BWD;
	    }
	  }
	}
	else {
	  double d = (pts[pj] - pts[prvj]).dist();

	  if (direc & D_FWD) {
	    edges[prvj][pj] = d;
	    nbrs[prvj].push_back(pj);
	  }
	  if (direc & D_BWD) {
	    edges[pj][prvj] = d;
	    nbrs[pj].push_back(prvj);
	  }

	  prvj = pj;
	  direc = D_BOTH;
	}
      }
    }

    for (int i = 0; i < npts; i++) {
      dists[i] = INF;
      prevs[i] = -1;
    }

    int sti = find(pts, pts + npts, st) - pts;
    int gli = find(pts, pts + npts, gl) - pts;
    
    dists[sti] = 0.0;
    vector<int> q;
    q.push_back(sti);
    CompDist compdist;
    
    while (! q.empty()) {
      sort(q.begin(), q.end(), compdist);
      int u = q.back();
      q.pop_back();

      if (u == gli) break;

      for (vi::iterator vit = nbrs[u].begin(); vit != nbrs[u].end(); vit++) {
	int v = *vit;
	double vd = dists[u] + edges[u][v];
	if (dists[v] > vd) {
	  if (dists[v] >= INF) q.push_back(v);
	  dists[v] = vd;
	  prevs[v] = u;
	}
      }
    }

    //for (int i = 0; i < npts; i++)
    //printf("dists[%d] = %lf\n", i, dists[i]);
    
    if (prevs[gli] < 0)
      cout << -1 << endl;
    else {
      di path;
      int u = gli;
      while (u >= 0) {
	path.push_front(u);
	u = prevs[u];
      }

      for (di::iterator pit = path.begin(); pit != path.end(); pit++) {
	Pt& pt = pts[*pit];
	cout << pt.x << ' ' << pt.y << endl;
      }
      cout << 0 << endl;
    }
  }

  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 1904
final_rank: 4

code_snippet: #include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
using namespace std;
int G[510][510];
int L[510][510];
int x[510];
int y[510];
int cnt[510];
vector<int>g[510];
double ijk[510];
int v[510];
int rev[510];
int ans[510];
int tc[510];
int p[510];
int q[510];
int r[510];
int s[510];
int ABS(int a){return max(a,-a);}
int dcalc(int a,int b,int c,int d){
	return (x[b]-x[a])*(x[d]-x[c])+(y[b]-y[a])*(y[d]-y[c]);
}
double dist(int a,int b){
	return sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));
}
int ccw(int a,int b,int c,int d,int e,int f){
	int X1=c-a;int X2=e-a;
	int Y1=d-b;int Y2=f-b;
	if(X1*Y2!=Y1*X2)return 0;
	if(X1*X2<0)return 0;
	if(Y1*Y2<0)return 0;
	if(ABS(X1)<ABS(X2))return 0;
	if(ABS(Y1)<ABS(Y2))return 0;
	return 1;
}
int main(){
	int a;
	while(scanf("%d",&a),a){
		int sx,sy,gx,gy;
		scanf("%d%d%d%d",&sx,&sy,&gx,&gy);
		int sz=0;
		map<pair<int,int>,int> m;
		for(int i=0;i<510;i++)g[i].clear();
		for(int i=0;i<510;i++)tc[i]=0;
		for(int i=0;i<510;i++)cnt[i]=0;
		for(int i=0;i<510;i++)for(int j=0;j<510;j++){
			G[i][j]=0;
			L[i][j]=-1;
		}
		for(int i=0;i<a;i++){
			scanf("%d%d%d%d",p+i,q+i,r+i,s+i);
			int from=-1;
			int to=-1;
			if(m.count(make_pair(p[i],q[i]))){
				from=m[make_pair(p[i],q[i])];
			}else{
				m[make_pair(p[i],q[i])]=sz;
				x[sz]=p[i];y[sz]=q[i];
				from=sz++;
			}
			if(m.count(make_pair(r[i],s[i]))){
				to=m[make_pair(r[i],s[i])];
			}else{
				m[make_pair(r[i],s[i])]=sz;
				x[sz]=r[i];y[sz]=s[i];
				to=sz++;
			}
		}
		for(int i=0;i<a;i++){
			vector<pair<double,int> > o;
			int ss=m[make_pair(p[i],q[i])];
			for(int j=0;j<sz;j++){
				if(ccw(p[i],q[i],r[i],s[i],x[j],y[j])){
					o.push_back(make_pair(dist(ss,j),j));
				}
			}
			std::sort(o.begin(),o.end());
			for(int j=0;j<o.size()-1;j++){
				int E=o[j].second;
				int F=o[j+1].second;
				G[E][F]=G[F][E]=1;
				cnt[E]++;
				cnt[F]++;
			}
		}
	/*	for(int i=0;i<sz;i++){
			if(x[i]==364&&y[i]==0){
				for(int j=0;j<sz;j++)if(G[i][j])printf("%d %d\n",x[j],y[j]);
			}
		}*/
		for(int i=0;i<sz;i++){
			if(cnt[i]==1){
				for(int j=0;j<sz;j++)if(G[i][j]){
					vector<int>t;
					vector<int>u;
					int rem=0;
					for(int k=0;k<sz;k++){
						if(G[j][k]&&cnt[k]!=1)t.push_back(k);
						else if(G[j][k])u.push_back(k);
					}
				//	printf("%d,%d: %d\n",x[i],y[i],t.size());
				//	G[i][j]=G[j][i]=0;
					G[j][t[0]]=G[t[0]][j]=0;
					G[j][t[1]]=G[t[1]][j]=0;
					G[t[0]][t[1]]=G[t[1]][t[0]]=1;
					L[t[0]][t[1]]=L[t[0]][j];
					if(~L[t[0]][t[1]]&&~L[j][t[1]])L[t[0]][t[1]]&=L[j][t[1]];
					else if(!~L[t[0]][t[1]])L[t[0]][t[1]]=L[j][t[1]];
					L[t[1]][t[0]]=L[j][t[0]];
					if(~L[t[1]][t[0]]&&~L[t[1]][j])L[t[1]][t[0]]&=L[t[1]][j];
					else if(!~L[t[1]][t[0]])L[t[1]][t[0]]=L[t[1]][j];
					for(int k=0;k<u.size();k++){
					G[j][u[k]]=G[u[k]][j]=0;
					int dot=dcalc(t[0],t[1],j,u[k]);
					if(dot>0){
						//L[t[1]][t[0]]=1;
						L[t[0]][t[1]]=0;
					}else if(dot==0){
						L[t[0]][t[1]]=L[t[1]][t[0]]=0;
					}else{
						//L[t[0]][t[1]]=1;
						L[t[1]][t[0]]=0;
					}
					}
				}
			}
		}
		for(int i=0;i<sz;i++)for(int j=0;j<sz;j++){
			if(G[i][j]&&L[i][j]!=0){
				g[i].push_back(j);
//			if(x[i]==9||x[j]==9)printf("%d,%d %d,%d\n",x[i],y[i],x[j],y[j]);
			}
		}
		int S=m[make_pair(sx,sy)];
		int T=m[make_pair(gx,gy)];
		for(int i=0;i<sz;i++){
			ijk[i]=99999999;
			v[i]=0;
			rev[i]=-1;
		}
		priority_queue<pair<double,int> >Q;
		ijk[S]=0;
		Q.push(make_pair(0.0,S));
		while(Q.size()){
			double cost=-Q.top().first;
			int at=Q.top().second;
			Q.pop();
			if(v[at])continue;
			v[at]=1;
			for(int i=0;i<g[at].size();i++){
				if(!v[g[at][i]]&&ijk[g[at][i]]>cost+dist(at,g[at][i])){
					ijk[g[at][i]]=cost+dist(at,g[at][i]);
					rev[g[at][i]]=at;
					Q.push(make_pair(-ijk[g[at][i]],g[at][i]));
				}
			}
		}
		if(ijk[T]>9999999){
			printf("-1\n");continue;
		}
		int ind=0;
		int now=T;
		while(now!=S){
			ans[ind++]=now;
			now=rev[now];
		}
		ans[ind++]=S;
		for(int i=ind-1;i>=0;i--){
			printf("%d %d\n",x[ans[i]],y[ans[i]]);
		}
		printf("0\n");
	}
}
accuracy: 1
time_ms: 10
memory_kb: 3156
final_rank: 6

code_snippet: #include <string> 
#include <algorithm> 
#include <cfloat> 
#include <climits> 
#include <cmath> 
#include <complex> 
#include <cstdio> 
#include <cstdlib> 
#include <cstring> 
#include <functional> 
#include <iostream> 
#include <map> 
#include <memory> 
#include <queue> 
#include <set> 
#include <sstream> 
#include <stack> 
#include <utility> 
#include <vector> 

#define EACH(i,c) for(__typeof((c).begin()) i=(c).begin(); i!=(c).end(); ++i)
#define ALL(x) (x).begin(),(x).end() 
typedef long long ll;
using namespace std; 
const double eps = 1e-10;

const double INF = 1e+10;
typedef double Weight;
struct Edge{
    int from, to;
    Weight weight;
    int rev;     // ネットワークフロー時の逆辺
    Edge(int from, int to, Weight weight) :
        from(from), to(to), weight(weight) { }
    Edge(int from, int to, Weight weight, int rev) :
        from(from), to(to), weight(weight), rev(rev){ }
};
bool operator < (const Edge &a, const Edge &b){
    if(a.weight != b.weight) return a.weight > b.weight;
    if(a.from != b.from) return a.from > b.from;
    return  a.to > b.to;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void addFlowEdge(Graph &g, int a, int b, Weight c){
    g[a].push_back(Edge(a, b, c, g[b].size()));
    g[b].push_back(Edge(b, a, 0, g[a].size() - 1));
}
void addUndirectedEdge(Graph &g, int a, int b, Weight c){
    g[a].push_back(Edge(a, b, c, g[b].size()));
    g[b].push_back(Edge(b, a, c, g[a].size() - 1));
}

void dijkstra(const Graph &g, int s, vector<Weight> &dist, vector<int> &prev){
    int n = g.size();
    dist.assign(n, INF);
    dist[s] = 0;
    prev.assign(n, -1);
    priority_queue<Edge> Q;     // a < b <-> a.weight > b.weight
    Q.push(Edge(-2, s, 0));
    while(!Q.empty()){
        Edge e = Q.top(); Q.pop();
        if(prev[e.to] != -1) continue;
        prev[e.to] = e.from;
        EACH(i, g[e.to]){
        //for(Edges::const_iterator i=g[e.to].begin(); i!=g[e.to].end(); ++i){    //マクロが使えないとき
            if(dist[i -> to] > dist[i -> from] + i -> weight){
                dist[i -> to] = dist[i -> from] + i -> weight;
                Q.push(Edge(i -> from, i -> to, dist[i -> to]));
            }
        }
    }
}
vector<int> buildPath(const vector<int> &prev, int t){
    vector<int> path;
    for(int v = t; v >= 0; v = prev[v])
        path.push_back(v);
    reverse(path.begin(), path.end());
    return path;
}

typedef complex<double> P;

namespace std{
    bool operator<(const P&a, const P &b){
        if(a.real()==b.real()) return a.imag() < b.imag();
        else return a.real() < b.real();
    }
};
inline double dot(const P &a, const P &b){
    return real(conj(a) * b);
}
inline double cross(const P &a, const P &b){
    return imag(conj(a) * b);
}
int ccw(const P &a, P b, P c){
    b -= a; c -= a;
    if (cross(b, c) > eps)  return +1;  // ccw
    if (cross(b, c) < -eps) return -1;  // cw
    if (dot(b,c) < -eps)       return +2;  // c-a-b
    if (norm(b)+eps < norm(c))  return -2;  // a-b-c
    return 0;                           // a-c-b
}
struct Line : public vector<P> {
    Line() { }
    Line(const P &a, const P &b) {
        push_back(a); push_back(b);
    }
};
inline bool parallel(const Line &s, const Line &t){
    return abs(cross(s[1]-s[0], t[1]-t[0])) < eps;
}
inline bool orthogonal(const Line &s, const Line &t){
    return abs(dot(s[1]-s[0], t[1]-t[0])) < eps;
}
P projection(const Line &s, const P &a){
    P v = s[1] - s[0];
    return s[0] + dot(v, a - s[0]) / abs(v) / abs(v) * v;
}
P reflection(const Line &s, const P &a){
    P p = projection(s, a);
    return 2.0 * p - a;
}
struct Segment : public Line {
    Segment(const P &a, const P &b) : Line(a,b) { }
};
struct Circle{
    P o;
    double r;
    Circle() { }
    Circle(const P &o, double r) : o(o), r(r) { }
    Circle(double x, double y, double r) : o(x,y), r(r) { }
    inline bool contains(const P &p) const{
        return abs(p-o) < r + eps;
    }
    inline bool inside(const P &p) const{
        return abs(p-o) < r - eps;
    }
    pair<Line,Line> tangent(const P &p) const{
        vector<Line> res;
        double d = abs(p - o), s = r*r / d, t = sqrt(r*r-s*s);
        P q = o + s/d * (p - o), e = (p - o) * P(0, 1/d); 
        return make_pair(Line(p,q+e*t), Line(p,q-e*t));
    }
};
typedef vector<P> Polygon;
#define curr(p,i) p[i]
#define next(p,i) p[(i+1)%p.size()]
inline bool intersectSS(const Segment &s, const Segment &t){
    return ccw(s[0],s[1],t[0]) * ccw(s[0],s[1],t[1]) <= eps &&
           ccw(t[0],t[1],s[0]) * ccw(t[0],t[1],s[1]) <= eps;
}
// TODO:端点の扱いが雑なのを何とかする．
P crosspointSS(const Segment &s, const Segment &t){
    double a = cross(s[1] - s[0], t[1] - t[0]);
    double b = cross(s[1] - s[0], s[1] - t[0]);
    if(abs(a) < eps && abs(b) < eps) return s[0];   // same line
    // if(abs(a) < eps) assert(false);
    return t[0] + b/a * (t[1] - t[0]);
}

Graph segmentArrangement(const vector<Segment> &ss, vector<P> &ps){
    for(int i = 0; i < ss.size(); ++i){
        ps.push_back(ss[i][0]);
        ps.push_back(ss[i][1]);
        for(int j=i+1;j<ss.size();++j){
            if(intersectSS(ss[i], ss[j]))
                ps.push_back(crosspointSS(ss[i], ss[j]));
        }
    }
    sort(ALL(ps)); ps.erase(unique(ALL(ps)), ps.end());
    Graph g(ps.size());
    for(int i=0;i<ss.size();++i){
        vector<pair<double, int> > lst;
        for(int j=0;j<ps.size();++j){
            if(ccw(ss[i][0], ss[i][1], ps[j]) == 0)
                lst.push_back(make_pair(norm(ss[i][0]-ps[j]), j));
        }
        sort(ALL(lst));
        for(int j=0;j+1<lst.size();++j){
            int a = lst[j].second, b = lst[j+1].second;
            addUndirectedEdge(g, a, b, abs(ps[a]-ps[b]));
        }
    }
    return g;
}
int main(){
    for(;;){
        int n;
        cin >> n;
        if(n == 0) return 0;
        P s, g;
        vector<Segment> v;
        int x, y;
        cin >> x >> y; s=P(x,y);
        cin >> x >> y; g=P(x,y);
        for(int i = 0; i < n; ++i){
            int x1, y1, x2, y2;
            cin >> x1 >> y1 >> x2 >> y2;
            v.push_back(Segment(P(x1,y1), P(x2,y2)));
        }
        vector<Segment> road, signs;
        for(int i = 0; i < n; ++i){
            int f = 0;
            for(int j=0;j<n;++j) if(i != j) for(int k=0;k<2;++k){
                if(ccw(v[j][0], v[j][1], v[i][k]) == 0)
                    f |= 1 << k;
            }
            if(f == 3) road.push_back(v[i]);
            else signs.push_back(v[i]);
        }
        vector<P> ps;
        Graph graph = segmentArrangement(road, ps);
        int si, gi;
        for(int i=0;i<ps.size();++i) if(abs(ps[i]-s) < eps) si = i;
        for(int i=0;i<ps.size();++i) if(abs(ps[i]-g) < eps) gi = i;

        EACH(i, signs){
            Segment ss = *i;
            EACH(j, graph) EACH(k, *j) {
                int a = k->from, b = k->to;
                bool f = true;
                double d = 1;
                if(ccw(ps[a], ps[b], ss[0]) == 0){
                    d = dot(ss[0]-ss[1], ps[b]-ps[a]);
                }
                else if(ccw(ps[a], ps[b], ss[1]) == 0){
                    d = dot(ss[1]-ss[0], ps[b]-ps[a]);
                }
                if(d < eps){
                    k->weight = INF;
                }
            }
        }

        vector<int> prev(ps.size(),-1);
        vector<Weight> dist(ps.size());
        dijkstra(graph, si, dist, prev);
        if(dist[gi] == INF){
            cout << -1 << endl;
        }
        else{
            vector<int> path = buildPath(prev, gi);
            EACH(i, path){
                cout << (int)ps[*i].real() << " " << (int)ps[*i].imag() << endl;
            }
            cout << 0 << endl;
        }
    }
}
accuracy: 1
time_ms: 10
memory_kb: 1320
final_rank: 1

code_snippet: #include <iostream>
#include <cmath>
#include <complex>
#include <vector>
#include <algorithm>
#include <cstdio>
#define rep(i,n) for(int i=0;i<n;i++)
#define fs first
#define sc second
#define X real()
#define Y imag()
#define pb push_back
#define all(c) c.begin(),c.end()
#define show(x) cout<<#x<<" : "<<x<<endl
using namespace std;
typedef double D;
typedef complex<D> P;
typedef pair<P,P> L;
D inf=1e50,eps=1e-10,pi=acos(0.0)*2;
bool eq(D a,D b){
	return abs(a-b)<eps;
}
bool compxy(const P& l,const P& r){
	return eq(l.X,r.X) ? l.Y<r.Y : l.X<r.X;
}
bool on(L l,P p){
	return (eq(abs(l.fs-p)+abs(l.sc-p),abs(l.fs-l.sc)));
}
int N,M;
int sx,sy,gx,gy;
vector<L> lines;
vector<P> points;
vector<P> online[200];
vector<int> ans;
bool sign[200];
int ne[200][200];
D d[200][200];
int id(P p){
	return lower_bound(all(points),p,compxy)-points.begin();
}
int pre[200];
D dist[200];
void dijkstra(int s){
	bool used[200]={};
	rep(i,M) dist[i]=inf;
	dist[s]=0;
	rep(i,M){
		int u=-1;
		rep(j,M) if(!used[j]&&(u==-1||dist[u]>dist[j])) u=j;
		if(u==-1) break;
		used[u]=true;
		rep(j,M){
			if(dist[j]>dist[u]+d[u][j]){
				dist[j]=dist[u]+d[u][j];
				pre[j]=u;
			}
		}
	}
}
int main(){
	while(true){
		cin>>N;
		if(N==0) break;
		lines.clear();
		points.clear();
		ans.clear();
		rep(i,N) sign[i]=false;
		rep(i,N) online[i].clear();
		cin>>sx>>sy>>gx>>gy;
		rep(i,N){
			int x,y,z,w;
			cin>>x>>y>>z>>w;
			lines.pb(L(P(x,y),P(z,w)));
		}
		rep(i,N){
			P &a=lines[i].fs,&b=lines[i].sc;
			bool aon=false,bon=false;
			rep(j,N) if(i!=j&&on(lines[j],a)) aon=true;
			rep(j,N) if(i!=j&&on(lines[j],b)) bon=true;
			if(!aon||!bon) sign[i]=true;
			else{
				points.pb(a);
				points.pb(b);
				rep(j,N){
					if(on(lines[j],a)) online[j].pb(a);
					if(on(lines[j],b)) online[j].pb(b);
				}
			}
		}
		sort(all(points),compxy);
		points.erase(unique(all(points)),points.end());
		M=points.size();
		rep(i,N) if(!sign[i]){
			sort(all(online[i]),compxy);
			online[i].erase(unique(all(online[i])),online[i].end());
		}
		rep(i,M) rep(j,M) if(i!=j) d[i][j]=inf;
		rep(i,N) if(!sign[i]){
			rep(j,online[i].size()-1){
				int x=id(online[i][j]),y=id(online[i][j+1]);
				d[x][y]=d[y][x]=abs(online[i][j]-online[i][j+1]);
			}
		}
/*		rep(i,N) if(!sign[i]){
			rep(j,online[i].size()) cout<<online[i][j]<<"  ";
			cout<<endl;
		}*/
		rep(i,N) if(sign[i]){
			P &a=lines[i].fs,&b=lines[i].sc;
			rep(j,N) if(!sign[j]){
				if(on(lines[j],b)) swap(a,b);
				if(on(lines[j],a)){
//					show(a);
//					rep(k,online[j].size()) cout<<online[j][k]<<endl;
//					int iid=lower_bound(all(online[j]),a,compxy)-online[j].begin();
//					show(iid);
					P y=*lower_bound(all(online[j]),a,compxy),x=*(lower_bound(all(online[j]),a,compxy)-1);
					D theta=abs(arg((b-a)/(y-x)));
					D a=theta-pi/2.0;
					if(a<=eps) d[id(x)][id(y)]=inf;
					if(a>=-eps) d[id(y)][id(x)]=inf;
				}
			}
		}
		int s=id(P(sx,sy)),g=id(P(gx,gy));
		dijkstra(s);
		if(dist[g]==inf){
			puts("-1");
			continue;
		}
		while(s!=g){
			ans.pb(g);
			g=pre[g];
		}
		ans.pb(s);
		rep(i,ans.size()){
			int x=ans[ans.size()-1-i];
			cout<<(int)points[x].X<<" "<<(int)points[x].Y<<endl;
		}
		puts("0");
	}
}
accuracy: 1
time_ms: 50
memory_kb: 1560
final_rank: 14

code_snippet: #include <algorithm>
#include <climits>
#include <cmath>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;

constexpr double EPS = 1e-9;

struct point {
	double x, y;
	point(double x_ = 0.0, double y_ = 0.0):x(x_), y(y_) {}
	point(const point &p):x(p.x), y(p.y) {}

	point operator+ (const point &p) const {
		return point(x + p.x, y + p.y);
	}

	point operator- (const point &p) const {
		return point(x - p.x, y - p.y);
	}

	point operator* (double s) const {
		return point(x * s, y * s);
	}

	point operator* (const point &p) const {
		return point(x * p.x - y * p.y, x * p.y + y * p.x);
	}

	point operator/ (double s) const {
		return point(x / s, y / s);
	}

	bool operator< (const point &p) const {
		return x + EPS < p.x || (abs(x - p.x) < EPS && y + EPS < p.y);
	}

	bool operator== (const point &p) const {
		return abs(x - p.x) < EPS && abs(y - p.y) < EPS;
	}
};

istream &operator>>(istream &is, point &p) {
	return is >> p.x >> p.y;
}

point rotate90(const point &p) {
	return point(-p.y, p.x);
}

double norm(const point &p) {
	return p.x * p.x + p.y * p.y;
}

double abs(const point &p) {
	return sqrt(norm(p));
}

double dot(const point &a, const point &b) {
	return a.x * b.x + a.y * b.y;
}

double cross(const point &a, const point &b) {
	return a.x * b.y - a.y * b.x;
}

struct segment {
	point a, b;
	segment(const point &a_, const point &b_):a(a_), b(b_){}
};

struct circle {
	point c;
	double r;
	circle(const point &c_, const double &r_):c(c_), r(r_){}
};

typedef vector<point> polygon;

int ccw(const point &a, point b, point c) {
	b = b - a;
	c = c - a;
	const double tmp = cross(b, c);
	if(tmp > EPS) return 1; // ccw
	if(tmp < -EPS) return -1; // cw
	if(dot(b, c) < 0) return 2; // c, a, b 順に一直線上
	if(norm(b) < norm(c)) return -2; // a, b, c 順に一直線上
	return 0; //a, c, b 順で一直線上
}

bool intersect(const segment &s, const segment &t) {
	return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0
		&& ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

bool intersect(const segment &s, const point &p) {
	return ccw(s.a, s.b, p) == 0;
}

point crosspoint(const segment &s, const segment &t) {
	if(!intersect(s, t)) return s.a; // 交点を持たない

	const double tmp = cross(s.b - s.a, t.b - t.a);
	if(abs(tmp) < EPS) { // 一直線上
		if(intersect(s, t.a)) return t.a;
		if(intersect(s, t.b)) return t.b;
		if(intersect(t, s.a)) return s.a;
		return s.b;
	}
	return t.a + (t.b - t.a) * cross(s.b - s.a, s.b - t.a) * (1.0 / tmp);
}

struct edge {
	int to;
	double cost;
	edge(int to_, double cost_):to(to_), cost(cost_) {}
};

typedef vector<vector<edge>> graph;

int get_index(const vector<point> &points, const point &p) {
	return lower_bound(points.begin(), points.end(), p) - points.begin();
}

graph arrangement(const vector<segment> &segments, vector<point> &points) {
	vector<segment> streets, signs;

	for(int i = 0; i < static_cast<int>(segments.size()); ++i) {
		bool a_on = false, b_on = false;
		for(int j = 0; j < static_cast<int>(segments.size()); ++j) {
			if(i == j) continue;
			a_on |= intersect(segments[j], segments[i].a);
			b_on |= intersect(segments[j], segments[i].b);
		}

		(a_on && b_on ? streets : signs).emplace_back(segments[i]);
	}

	const int n = streets.size();
	points.clear();
	for(int i = 0; i < n; ++i) {
		const auto &s1 = streets[i];
		points.emplace_back(s1.a);
		points.emplace_back(s1.b);

		for(int j = i + 1; j < n; ++j) {
			const auto &s2 = streets[j];
			if(intersect(s1, s2)) {
				points.emplace_back(crosspoint(s1, s2));
			}
		}
	}

	sort(points.begin(), points.end());
	points.erase(unique(points.begin(), points.end()), points.end());

	const int V = points.size();
	graph G(V);

	for(const auto &s : streets) {
		vector<pair<double, int>> vs;
		for(int i = 0; i < V; ++i) {
			if(intersect(s, points[i])) {
				vs.emplace_back(abs(s.a - points[i]), i);
			}
		}

		sort(vs.begin(), vs.end());
		for(int i = 1; i < static_cast<int>(vs.size()); ++i) {
			const int v = vs[i].second;
			const int u = vs[i - 1].second;
			const double d = vs[i].first - vs[i - 1].first;

			bool go = true;
			bool back = true;

			const segment street(points[v], points[u]);

			for(const auto & t : signs) {
				const bool a_on = intersect(street, t.a);
				const bool b_on = intersect(street, t.b);

				if(a_on || b_on) {
					const point &base = (a_on ? t.a : t.b);
					const point &tip  = (a_on ? t.b : t.a);
					const int tmp = ccw(base, base + rotate90(points[u] - points[v]), tip);

					if(tmp != 1)  go = false;
					if(tmp != -1) back = false;
				}
			}

			if(go)   G[v].emplace_back(u, d);
			if(back) G[u].emplace_back(v, d);
		}
	}

	return G;
}

bool dijkstra(const graph &G, int s, int t, vector<int> &prev) {
	typedef pair<double, int> P;

	const int n = G.size();

	vector<double> dist(n, INT_MAX);
	priority_queue<P, vector<P>, greater<P>> que;

	dist[s] = 0;
	que.push({0, s});
	prev.assign(n, -1);

	while(!que.empty()) {
		const auto d = que.top().first;
		const auto v = que.top().second;
		que.pop();

		if(dist[v] + EPS < d) continue;

		if(v == t) return true;

		for(const auto &e : G[v]) {
			const auto next_dist = d + e.cost;
			if(dist[e.to] > next_dist + EPS) {
				dist[e.to] = next_dist;
				que.push({next_dist, e.to});
				prev[e.to] = v;
			}
		}
	}
	
	return false;
}

int main() {
	cin.tie(nullptr);
	ios::sync_with_stdio(false);

	for(int n; cin >> n && n;) {
		point start, goal;
		cin >> start >> goal;

		vector<segment> segments;
		segments.reserve(n);

		for(int i = 0; i < n; ++i) {
			point a, b;
			cin >> a >> b;
			segments.emplace_back(a, b);
		}

		vector<point> points;
		const auto G = arrangement(segments, points);

		const int start_index = get_index(points, start);
		const int goal_index = get_index(points, goal);

		vector<int> prev;
		if(!dijkstra(G, start_index, goal_index, prev)) {
			cout << -1 << '\n';
			continue;
		}

		vector<int> path;
		for(int v = goal_index; v != -1; v = prev[v]) {
			path.emplace_back(v);
		}
		reverse(path.begin(), path.end());

		for(const auto &idx : path) {
			cout << points[idx].x << ' ' << points[idx].y << '\n';
		}
		cout << "0\n";
	}

	return EXIT_SUCCESS;
}
accuracy: 1
time_ms: 10
memory_kb: 1388
final_rank: 3