Problem:
すぬけ君は，初期状態では動くことはできない．
i
番目のチケットの値段は
p
i
であり，これを買うと任意の
(x, y)
と任意の非負実数
t
に対し
(x, y)
から
(x + ta
i
, y + tb
i
)
に移動することができるようになる．すぬけ君が平面上の任意の二点間を(いくつかのチケットを組み合わせて) 移動できるようになるために買わなければならないチケットの合計金額の最小値を求めよ．
Constraints
1 ≤
n
≤ 200000
−10
9
≤
a
i
, b
i
≤ 10
9
1 ≤
p
i
≤ 10
9
入力は全て整数である
Input
n
a
1
b
1
p
1
. . .
a
n
b
n
p
n
Output
平面上の任意の二点間を移動できるようになるために買わなければならないチケットの合計金額の最小値を出力せよ．できない場合は-1 を出力せよ．
Sample Input 1
7
0 3 1
0 3 2
1 -1 2
0 0 1
-2 4 1
-4 0 1
2 1 2
たとえばチケット1, 3, 6 を買うとよい．
Sample Output 1
4
Sample Input 2
2
1 2 3
4 5 6
Sample Output 2
-1

Submitted solutions:

code_snippet: // AOJ #2634 Directions
// 2025.3.21

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

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int Cin() {  // 整数の入力
	int n = 0; int c = gc();
	if (c == '-') {	c = gc();
		do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
		return -n;
	}
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

void Cout(ll n) { // 整数の表示（出力）
	char b[30];
	if (!n) pc('0');
	else {
		if (n < 0) pc('-'), n = -n;
		int i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
		while (i--) pc(b[i]);
	}
	pc('\n');
}

struct Vec {
    ll x, y, price;

    Vec() {}
    Vec(ll x, ll y, ll price) : x(x), y(y), price(price) {}

    ll dot(const Vec &v) const {
        return x * v.x + y * v.y;
    }

    ll cross(const Vec &v) const {
        return x * v.y - y * v.x;
    }

    ll operator * (const Vec &v) const {
        return cross(v);
    }
};

const ll INF = 20000000000LL;

int main() {
    int n = Cin();

    vector<Vec> groupX, groupY;
    for (int i = 0; i < n; i++) {
        ll x = Cin(), y = Cin(), price = Cin();
        if (x == 0 && y == 0) continue;
        if (x > 0 || (x == 0 && y > 0)) groupX.push_back(Vec(x, y, price));
        else groupY.push_back(Vec(x, y, price));
    }

    auto cmpByCross = [](const Vec &a, const Vec &b) {
        return a * b > 0;
    };
    sort(groupX.begin(), groupX.end(), cmpByCross);
    sort(groupY.begin(), groupY.end(), cmpByCross);

    ll ans = INF;

    for (int iter = 0; iter < 2; iter++) {
        size_t sizeX = groupX.size();
        vector<ll> leftMin(sizeX), rightMin(sizeX);
        for (size_t i = 0; i < sizeX; i++) {
            leftMin[i] = groupX[i].price;
            if (i > 0) leftMin[i] = min(leftMin[i], leftMin[i - 1]);
        }
        for (int i = static_cast<int>(sizeX) - 1; i >= 0; i--) {
            rightMin[i] = groupX[i].price;
            if (i + 1 < sizeX) rightMin[i] = min(rightMin[i], rightMin[i + 1]);
        }

        size_t sizeY = groupY.size();
        size_t pointerL = 0, pointerR = 0;
        for (size_t j = 0; j < sizeY; j++) {
            while (pointerL < sizeX && groupY[j] * groupX[pointerL] > 0) pointerL++;
            while (pointerR < sizeX && groupY[j] * groupX[pointerR] >= 0) pointerR++;
            if (pointerL == 0 || pointerR == sizeX) continue;
            ans = min(ans, groupY[j].price + leftMin[pointerL - 1] + rightMin[pointerR]);
        }
        swap(groupX, groupY);
    }
    {
        size_t sizeX = groupX.size(), sizeY = groupY.size();
        size_t index = 0, pointerLower = 0, pointerUpper = 0;
        ll cumulativeMin = INF;
        while (index < sizeX) {
            ll xCost = INF, yCost = INF;
            size_t nextIndex = index;
            while (nextIndex < sizeX && (groupX[index] * groupX[nextIndex]) == 0) {
                xCost = min(xCost, groupX[nextIndex].price);
                nextIndex++;
            }
            for (pointerLower = pointerUpper; pointerLower < sizeY && groupX[index] * groupY[pointerLower] > 0; pointerLower++);
            for (pointerUpper = pointerLower; pointerUpper < sizeY && groupX[index] * groupY[pointerUpper] >= 0; pointerUpper++) {
                yCost = min(yCost, groupY[pointerUpper].price);
            }
            ans = min(ans, cumulativeMin + xCost + yCost);
            cumulativeMin = min(cumulativeMin, xCost + yCost);
            index = nextIndex;
        }
    }

    if (ans > 10000000000LL) Cout(-1);
    else Cout(ans);
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 12336
final_rank: 1

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

// ===================================================================== Segment Trees =====================================================================
const long long INF = 100LL * 1000LL * 1000LL * 1000LL;

class RangeAddMin {
public:
	int size_ = 1;
	vector<long long> dat;
	vector<long long> lazy;

	void init(int sz) {
		size_ = 1;
		while (size_ <= sz) size_ *= 2;
		dat.resize(size_ * 2, 0);
		lazy.resize(size_ * 2, 0);
	}

	void refresh(int u) {
		if (u < size_) {
			lazy[u * 2 + 0] += lazy[u];
			lazy[u * 2 + 1] += lazy[u];
			lazy[u] = 0;
			dat[u] = min(dat[u * 2 + 0] + lazy[u * 2 + 0], dat[u * 2 + 1] + lazy[u * 2 + 1]);
		}
		else {
			dat[u] += lazy[u];
			lazy[u] = 0;
		}
	}

	void add_(int l, int r, long long x, int a, int b, int u) {
		if (l <= a && b <= r) { lazy[u] += x; refresh(u); return; }
		if (r <= a || b <= l) return;
		refresh(u);
		add_(l, r, x, a, (a + b) / 2, u * 2 + 0);
		add_(l, r, x, (a + b) / 2, b, u * 2 + 1);
		refresh(u);
	}

	void add(int l, int r, long long x) {
		add_(l, r, x, 0, size_, 1);
	}
	
	long long query_(int l, int r, int a, int b, int u) {
		if (l <= a && b <= r) { refresh(u); return dat[u]; }
		if (r <= a || b <= l) return INF;
		refresh(u);
		long long v1 = query_(l, r, a, (a + b) / 2, u * 2 + 0);
		long long v2 = query_(l, r, (a + b) / 2, b, u * 2 + 1);
		refresh(u);
		return min(v1, v2);
	}

	long long query(int l, int r) {
		return query_(l, r, 0, size_, 1);
	}
};

class RangeAddMin_Naive {
public:
	int size_ = 1;
	vector<long long> dat;

	void init(int sz) {
		size_ = sz;
		dat.resize(size_ + 2, 0);
	}

	void add(int l, int r, long long x) {
		for (int i = l; i < r; i++) dat[i] += x;
	}

	long long query(int l, int r) {
		long long minx = INF;
		for (int i = l; i < r; i++) minx = min(minx, dat[i]);
		return minx;
	}
};

// ===================================================================== Struct & Variables =====================================================================
struct Ticket {
	long long px, py;
	long long price;
};

bool operator<(const Ticket& a1, const Ticket& a2) {
	int sgn1 = 0;
	int sgn2 = 0;
	if (a1.py < 0 || (a1.py == 0 && a1.px < 0)) sgn1 = 1;
	if (a2.py < 0 || (a2.py == 0 && a2.px < 0)) sgn2 = 1;
	if (sgn1 < sgn2) return true;
	if (sgn1 > sgn2) return false;
	if (a1.px * a2.py > a1.py * a2.px) return true;
	if (a1.px * a2.py < a1.py * a2.px) return false;
	if (a1.price < a2.price) return true;
	return false;
}

int N;
int cl[200009];
int cr[200009];
vector<Ticket> G;
RangeAddMin X1;
RangeAddMin X2;
vector<pair<int, int>> Stair;

// ===================================================================== Main Part =====================================================================
void AddToStair(int pos, int x) {
	int Left = pos;
	int Rigt = pos + 1;

	// Update Part 1
	while (Stair.size() > 0) {
		if (Stair[Stair.size() - 1].first <= x) break;
		int cur = Stair[Stair.size() - 1].second;
		int nex = N; if (Stair.size() >= 2) nex = Stair[Stair.size() - 2].second;
		int pos1 = lower_bound(cr, cr + N, cur) - cr;
		int pos2 = lower_bound(cr, cr + N, nex) - cr;
		X1.add(pos1, pos2, INF - (long long)Stair[Stair.size() - 1].first);
		Stair.pop_back();
	}
	if (Stair.size() == 0) Rigt = N;
	if (Stair.size() >= 1) Rigt = Stair[Stair.size() - 1].second;

	// Update Part 2
	int pos3 = lower_bound(cr, cr + N, Left) - cr;
	int pos4 = lower_bound(cr, cr + N, Rigt) - cr;
	X1.add(pos3, pos4, (long long)x - INF);
	Stair.push_back(make_pair(x, pos));
}

int main() {
	// Step 1. Input & Sort
	cin >> N;
	for (int i = 1; i <= N; i++) {
		long long p, q, r;
		cin >> p >> q >> r;
		// p = rand() % 1001 - 500;
		// q = rand() % 1001 - 500;
		// r = rand() % 1001 + 1;
		if (p != 0 || q != 0) G.push_back(Ticket{ p, q, r });
	}
	N = G.size();
	sort(G.begin(), G.end());

	// Step 2. Calculate Threshold
	int Start = -1;
	for (int i = 0; i < N; i++) {
		int pos1 = lower_bound(G.begin(), G.end(), Ticket{ -G[i].px, -G[i].py, -2000000000LL }) - G.begin();
		int pos2 = lower_bound(G.begin(), G.end(), Ticket{ -G[i].px, -G[i].py, +2000000000LL }) - G.begin();
		cl[i] = pos2;
		cr[i] = pos1 - 1; if (i > pos1) cr[i] = N - 1;
		if (i < cl[i]) Start = i;
	}

	// Step 3. Calculate 3-Tickets Case: Init
	long long Answer3 = (1LL << 60);
	int cur = N;
	X1.init(N + 2);
	X1.add(0, N, INF);
	for (int i = 0; i < N; i++) X1.add(i, i + 1, G[i].price);

	// Step 4. Calculate 3-Tickets Case: Main
	for (int i = Start; i >= 0; i--) {
		while (cl[i] < cur) {
			cur -= 1;
			AddToStair(cur, G[cur].price);
		}
		long long minv = X1.query(i + 1, cr[i] + 1);
		Answer3 = min(Answer3, minv + G[i].price);
	}

	// Step 5. Calculate 4-Tickets Case: Init
	X2.init(2 * (N + 2));
	for (int i = 0; i < N; i++) X2.add(i, i + 1, G[i].price);
	for (int i = 0; i < N; i++) X2.add(N + i, N + i + 1, G[i].price);

	// Step 6. Calculate 4-Tickets Case: Main
	long long Answer4 = (1LL << 60);
	for (int i = 0; i < N; i++) {
		int pos1 = lower_bound(G.begin(), G.end(), Ticket{ -G[i].px, -G[i].py, -2000000000LL }) - G.begin();
		int pos2 = lower_bound(G.begin(), G.end(), Ticket{ -G[i].px, -G[i].py, +2000000000LL }) - G.begin();
		int pos3 = lower_bound(G.begin(), G.end(), Ticket{ +G[i].px, +G[i].py, -2000000000LL }) - G.begin();
		int pos4 = lower_bound(G.begin(), G.end(), Ticket{ +G[i].px, +G[i].py, +2000000000LL }) - G.begin();
		if (pos1 < i || pos1 == pos2) continue;
		long long cost1 = G[i].price;
		long long cost2 = X2.query(pos1, pos2);
		long long cost3 = X2.query(pos4, pos1);
		long long cost4 = X2.query(pos2, N + pos3);
		Answer4 = min(Answer4, cost1 + cost2 + cost3 + cost4);
	}

	// Step 7. Output
	long long FinalAns = min(Answer3, Answer4);
	if (FinalAns >= INF) cout << "-1" << endl;
	else cout << FinalAns << endl;
	return 0;
}
accuracy: 1
time_ms: 420
memory_kb: 36812
final_rank: 5

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

// ===================================================================== Segment Trees =====================================================================
const long long INF = 100LL * 1000LL * 1000LL * 1000LL;

class RangeAddMin {
public:
	int size_ = 1;
	vector<long long> dat;
	vector<long long> lazy;

	void init(int sz) {
		size_ = 1;
		while (size_ <= sz) size_ *= 2;
		dat.resize(size_ * 2, 0);
		lazy.resize(size_ * 2, 0);
	}

	void refresh(int u) {
		if (u < size_) {
			lazy[u * 2 + 0] += lazy[u];
			lazy[u * 2 + 1] += lazy[u];
			lazy[u] = 0;
			dat[u] = min(dat[u * 2 + 0] + lazy[u * 2 + 0], dat[u * 2 + 1] + lazy[u * 2 + 1]);
		}
		else {
			dat[u] += lazy[u];
			lazy[u] = 0;
		}
	}

	void add_(int l, int r, long long x, int a, int b, int u) {
		if (l <= a && b <= r) { lazy[u] += x; refresh(u); return; }
		if (r <= a || b <= l) return;
		refresh(u);
		add_(l, r, x, a, (a + b) / 2, u * 2 + 0);
		add_(l, r, x, (a + b) / 2, b, u * 2 + 1);
		refresh(u);
	}

	void add(int l, int r, long long x) {
		add_(l, r, x, 0, size_, 1);
	}
	
	long long query_(int l, int r, int a, int b, int u) {
		if (l <= a && b <= r) { refresh(u); return dat[u]; }
		if (r <= a || b <= l) return INF;
		refresh(u);
		long long v1 = query_(l, r, a, (a + b) / 2, u * 2 + 0);
		long long v2 = query_(l, r, (a + b) / 2, b, u * 2 + 1);
		refresh(u);
		return min(v1, v2);
	}

	long long query(int l, int r) {
		return query_(l, r, 0, size_, 1);
	}
};

class RangeAddMin_Naive {
public:
	int size_ = 1;
	vector<long long> dat;

	void init(int sz) {
		size_ = sz;
		dat.resize(size_ + 2, 0);
	}

	void add(int l, int r, long long x) {
		for (int i = l; i < r; i++) dat[i] += x;
	}

	long long query(int l, int r) {
		long long minx = INF;
		for (int i = l; i < r; i++) minx = min(minx, dat[i]);
		return minx;
	}
};

// ===================================================================== Struct & Variables =====================================================================
struct Ticket {
	long long px, py;
	long long price;
};

bool operator<(const Ticket& a1, const Ticket& a2) {
	int sgn1 = 0;
	int sgn2 = 0;
	if (a1.py < 0 || (a1.py == 0 && a1.px < 0)) sgn1 = 1;
	if (a2.py < 0 || (a2.py == 0 && a2.px < 0)) sgn2 = 1;
	if (sgn1 < sgn2) return true;
	if (sgn1 > sgn2) return false;
	if (a1.px * a2.py > a1.py * a2.px) return true;
	if (a1.px * a2.py < a1.py * a2.px) return false;
	if (a1.price < a2.price) return true;
	return false;
}

int N;
int cl[200009];
int cr[200009];
vector<Ticket> G;
RangeAddMin X1;
RangeAddMin X2;
vector<pair<int, int>> Stair;

// ===================================================================== Main Part =====================================================================
void AddToStair(int pos, int x) {
	int Left = pos;
	int Rigt = pos + 1;

	// Update Part 1
	while (Stair.size() > 0) {
		if (Stair[Stair.size() - 1].first <= x) break;
		int cur = Stair[Stair.size() - 1].second;
		int nex = N; if (Stair.size() >= 2) nex = Stair[Stair.size() - 2].second;
		int pos1 = lower_bound(cr, cr + N, cur) - cr;
		int pos2 = lower_bound(cr, cr + N, nex) - cr;
		X1.add(pos1, pos2, INF - (long long)Stair[Stair.size() - 1].first);
		Stair.pop_back();
	}
	if (Stair.size() == 0) Rigt = N;
	if (Stair.size() >= 1) Rigt = Stair[Stair.size() - 1].second;

	// Update Part 2
	int pos3 = lower_bound(cr, cr + N, Left) - cr;
	int pos4 = lower_bound(cr, cr + N, Rigt) - cr;
	X1.add(pos3, pos4, (long long)x - INF);
	Stair.push_back(make_pair(x, pos));
}

int main() {
	// Step 1. Input & Sort
	cin >> N;
	for (int i = 1; i <= N; i++) {
		long long p, q, r;
		cin >> p >> q >> r;
		// p = rand() % 1001 - 500;
		// q = rand() % 1001 - 500;
		// r = rand() % 1001 + 1;
		if (p != 0 || q != 0) G.push_back(Ticket{ p, q, r });
	}
	N = G.size();
	sort(G.begin(), G.end());

	// Step 2. Calculate Threshold
	int Start = -1;
	for (int i = 0; i < N; i++) {
		int pos1 = lower_bound(G.begin(), G.end(), Ticket{ -G[i].px, -G[i].py, -2000000000LL }) - G.begin();
		int pos2 = lower_bound(G.begin(), G.end(), Ticket{ -G[i].px, -G[i].py, +2000000000LL }) - G.begin();
		cl[i] = pos2;
		cr[i] = pos1 - 1; if (i > pos1) cr[i] = N - 1;
		if (i < cl[i]) Start = i;
	}

	// Step 3. Calculate 3-Tickets Case: Init
	long long Answer3 = (1LL << 60);
	int cur = N;
	X1.init(N + 2);
	X1.add(0, N, INF);
	for (int i = 0; i < N; i++) X1.add(i, i + 1, G[i].price);

	// Step 4. Calculate 3-Tickets Case: Main
	for (int i = Start; i >= 0; i--) {
		while (cl[i] < cur) {
			cur -= 1;
			AddToStair(cur, G[cur].price);
		}
		long long minv = X1.query(i + 1, cr[i] + 1);
		Answer3 = min(Answer3, minv + G[i].price);
	}

	// Step 5. Calculate 4-Tickets Case: Init
	X2.init(2 * (N + 2));
	for (int i = 0; i < N; i++) X2.add(i, i + 1, G[i].price);
	for (int i = 0; i < N; i++) X2.add(N + i, N + i + 1, G[i].price);

	// Step 6. Calculate 4-Tickets Case: Main
	long long Answer4 = (1LL << 60);
	for (int i = 0; i < N; i++) {
		int pos1 = lower_bound(G.begin(), G.end(), Ticket{ -G[i].px, -G[i].py, -2000000000LL }) - G.begin();
		int pos2 = lower_bound(G.begin(), G.end(), Ticket{ -G[i].px, -G[i].py, +2000000000LL }) - G.begin();
		if (pos1 < i || pos1 == pos2) continue;
		long long cost1 = G[i].price;
		long long cost2 = X2.query(pos1, pos2);
		long long cost3 = X2.query(i + 1, pos1);
		long long cost4 = X2.query(pos2 + 1, N + i);
		Answer4 = min(Answer4, cost1 + cost2 + cost3 + cost4);
	}

	// Step 7. Output
	long long FinalAns = min(Answer3, Answer4);
	if (FinalAns >= INF) cout << "-1" << endl;
	else cout << FinalAns << endl;
	return 0;
}
accuracy: 0.8837209302325582
time_ms: 400
memory_kb: 37144
final_rank: 9

code_snippet: #include <bits/stdc++.h>
#define lc (rt << 1)
#define rc (rt << 1) | 1
using namespace std;
typedef long long LL;
typedef long double LD;
const int MAXN = 400005;
const LD PI = acosl(-1.0);

int n;

struct Ticket {
    LL x, y;
    LL c;
    LL operator * (const Ticket &rhs) const {
        return x * rhs.x + y * rhs.y;
    }
    LL operator ^ (const Ticket &rhs) const {
        return x * rhs.y - y * rhs.x;
    }
} p[MAXN];

bool polar_cmp(Ticket a, Ticket b) {
    int da = (a.y > 0 || (a.y == 0 && a.x > 0));
    int db = (b.y > 0 || (b.y == 0 && b.x > 0));
    if (da != db) return da < db;
    if ((a ^ b) != 0) return (a ^ b) > 0;
    return a.c < b.c;
}

struct SegmentTree {
    LL mn[MAXN << 2];
    void Build(int rt, int b, int e) {
        if (b == e) {
            mn[rt] = p[b].c;
            return;
        }
        int mid = (b + e) >> 1;
        Build(lc, b, mid);
        Build(rc, mid + 1, e);
        mn[rt] = min(mn[lc], mn[rc]);
    }
    LL Query(int rt, int b, int e, int l, int r) {
        if (l <= b && e <= r) return mn[rt];
        int mid = (b + e) >> 1;
        if (r <= mid) return Query(lc, b, mid, l, r);
        if (l > mid) return Query(rc, mid + 1, e, l, r);
        return min(Query(lc, b, mid, l, r), Query(rc, mid + 1, e, l, r));
    }
} seg;

void solve() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%lld %lld %lld", &p[i].x, &p[i].y, &p[i].c);
        if (!p[i].x && !p[i].y) {
            --i; --n;
        }
    }
    if (!n) {
        printf("-1\n");
        return;
    }
    sort(p + 1, p + n + 1, polar_cmp);
    int m = 0;
    for (int i = 1; i <= n; ++i) {
        if (i == 1 || ((p[i] ^ p[m]) != 0 || (p[i] * p[m]) < 0)) {
            p[++m] = p[i];
        }
    }
    n = m;
    for (int i = 1; i <= n; ++i) {
        p[n + i] = p[i];
    }
    seg.Build(1, 1, n * 2);
    LL ans = 1e18;
    for (int i = 1, j = 0, k = 0, l = 0; i <= n; ++i) {
        j = max(j, i + 1);
        while (j < i + n && (p[i] ^ p[j]) > 0 && (p[i] * p[j]) > 0) {
            ++j;
        }
        k = max(k, j);
        while (k < i + n && (p[i] ^ p[k]) > 0) {
            ++k;
        }
        l = max(l, k);
        while (l < i + n && (p[i] ^ p[l]) <= 0 && (p[i] * p[l]) < 0) {
            ++l;
        }
        if ((p[i] ^ p[k]) == 0 && (p[i] * p[k]) < 0) {
            if (k - i > 1 && i + n - k > 1) {
                ans = min(ans, p[i].c + p[k].c + seg.Query(1, 1, n * 2, i + 1, k - 1) + seg.Query(1, 1, n * 2, k + 1, i + n - 1));
            }
            if (k - j > 0 && l - k > 1) {
                ans = min(ans, p[i].c + seg.Query(1, 1, n * 2, j, k - 1) + seg.Query(1, 1, n * 2, k + 1, l - 1));
            }
        } else {
            if (k - j > 0 && l - k > 0) {
                ans = min(ans, p[i].c + seg.Query(1, 1, n * 2, j, k - 1) + seg.Query(1, 1, n * 2, k, l - 1));
            }
        }
    }
    if (ans == 1e18) printf("-1\n");
    else printf("%lld\n", ans);
}

int main() {
    solve();
    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 23284
final_rank: 2

code_snippet: #include <bits/stdc++.h>
#define lc (rt << 1)
#define rc (rt << 1) | 1
using namespace std;
typedef long long LL;
typedef long double LD;
const int MAXN = 400005;
const LD PI = acosl(-1.0);

int n;

struct Ticket {
    LL x, y;
    LL c;
    LL operator * (const Ticket &rhs) const {
        return x * rhs.x + y * rhs.y;
    }
    LL operator ^ (const Ticket &rhs) const {
        return x * rhs.y - y * rhs.x;
    }
} p[MAXN];

bool polar_cmp(Ticket a, Ticket b) {
    int da = (a.y > 0 || (a.y == 0 && a.x > 0));
    int db = (b.y > 0 || (b.y == 0 && b.x > 0));
    if (da != db) return da < db;
    if ((a ^ b) != 0) return (a ^ b) > 0;
    return a.c < b.c;
}

struct SegmentTree {
    LL mn[MAXN << 2];
    void Build(int rt, int b, int e) {
        if (b == e) {
            mn[rt] = p[b].c;
            return;
        }
        int mid = (b + e) >> 1;
        Build(lc, b, mid);
        Build(rc, mid + 1, e);
        mn[rt] = min(mn[lc], mn[rc]);
    }
    LL Query(int rt, int b, int e, int l, int r) {
        if (l <= b && e <= r) return mn[rt];
        int mid = (b + e) >> 1;
        if (r <= mid) return Query(lc, b, mid, l, r);
        if (l > mid) return Query(rc, mid + 1, e, l, r);
        return min(Query(lc, b, mid, l, r), Query(rc, mid + 1, e, l, r));
    }
} seg;

void solve() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%lld %lld %lld", &p[i].x, &p[i].y, &p[i].c);
        if (!p[i].x && !p[i].y) {
            --i; --n;
        }
    }
    if (!n) {
        printf("-1");
        return;
    }
    sort(p + 1, p + n + 1, polar_cmp);
    int m = 0;
    for (int i = 1; i <= n; ++i) {
        if (i == 1 || ((p[i] ^ p[m]) != 0 || (p[i] * p[m]) < 0)) {
            p[++m] = p[i];
        }
    }
    n = m;
    for (int i = 1; i <= n; ++i) {
        p[n + i] = p[i];
    }
    seg.Build(1, 1, n * 2);
    LL ans = 1e18;
    for (int i = 1, j = 0, k = 0, l = 0; i <= n; ++i) {
        j = max(j, i + 1);
        while (j < i + n && (p[i] ^ p[j]) > 0 && (p[i] * p[j]) > 0) {
            ++j;
        }
        k = max(k, j);
        while (k < i + n && (p[i] ^ p[k]) > 0) {
            ++k;
        }
        l = max(l, k);
        while (l < i + n && (p[i] ^ p[l]) <= 0 && (p[i] * p[l]) < 0) {
            ++l;
        }
        if ((p[i] ^ p[k]) == 0 && (p[i] * p[k]) < 0) {
            if (k - i > 1 && i + n - k > 1) {
                ans = min(ans, p[i].c + p[k].c + seg.Query(1, 1, n * 2, i + 1, k - 1) + seg.Query(1, 1, n * 2, k + 1, i + n - 1));
            }
            if (k - j > 0 && l - k > 1) {
                ans = min(ans, p[i].c + seg.Query(1, 1, n * 2, j, k - 1) + seg.Query(1, 1, n * 2, k + 1, l - 1));
            }
        } else {
            if (k - j > 0 && l - k > 0) {
                ans = min(ans, p[i].c + seg.Query(1, 1, n * 2, j, k - 1) + seg.Query(1, 1, n * 2, k, l - 1));
            }
        }
    }
    if (ans == 1e18) printf("-1\n");
    else printf("%lld\n", ans);
}

int main() {
    solve();
    return 0;
}
accuracy: 0.0872093023255814
time_ms: 100
memory_kb: 23368
final_rank: 18

code_snippet: #include <bits/stdc++.h>
#define lc (rt << 1)
#define rc (rt << 1) | 1
using namespace std;
typedef long long LL;
typedef long double LD;
const int MAXN = 400005;
const LD PI = acosl(-1.0);

int n;

struct Ticket {
    LL x, y;
    LL c;
    LL operator * (const Ticket &rhs) const {
        return x * rhs.x + y * rhs.y;
    }
    LL operator ^ (const Ticket &rhs) const {
        return x * rhs.y - y * rhs.x;
    }
} p[MAXN];

bool polar_cmp(Ticket a, Ticket b) {
    int da = (a.y > 0 || (a.y == 0 && a.x > 0));
    int db = (b.y > 0 || (b.y == 0 && b.x > 0));
    if (da != db) return da < db;
    if ((a ^ b) != 0) return (a ^ b) > 0;
    return a.c < b.c;
}

struct SegmentTree {
    LL mn[MAXN << 2];
    void Build(int rt, int b, int e) {
        if (b == e) {
            mn[rt] = p[b].c;
            return;
        }
        int mid = (b + e) >> 1;
        Build(lc, b, mid);
        Build(rc, mid + 1, e);
        mn[rt] = min(mn[lc], mn[rc]);
    }
    LL Query(int rt, int b, int e, int l, int r) {
        if (l <= b && e <= r) return mn[rt];
        int mid = (b + e) >> 1;
        if (r <= mid) return Query(lc, b, mid, l, r);
        if (l > mid) return Query(rc, mid + 1, e, l, r);
        return min(Query(lc, b, mid, l, r), Query(rc, mid + 1, e, l, r));
    }
} seg;

void solve() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%lld %lld %lld", &p[i].x, &p[i].y, &p[i].c);
        if (!p[i].x && !p[i].y) {
            --i; --n;
        }
    }
    sort(p + 1, p + n + 1, polar_cmp);
    int m = 0;
    for (int i = 1; i <= n; ++i) {
        if (i == 1 || ((p[i] ^ p[m]) != 0 || (p[i] * p[m]) < 0)) {
            p[++m] = p[i];
        }
    }
    n = m;
    for (int i = 1; i <= n; ++i) {
        p[n + i] = p[i];
    }
    seg.Build(1, 1, n * 2);
    LL ans = 1e18;
    for (int i = 1, j = 0, k = 0, l = 0; i <= n; ++i) {
        j = max(j, i + 1);
        while (j < i + n && (p[i] ^ p[j]) > 0 && (p[i] * p[j]) > 0) {
            ++j;
        }
        k = max(k, j);
        while (k < i + n && (p[i] ^ p[k]) > 0) {
            ++k;
        }
        l = max(l, k);
        while (l < i + n && (p[i] ^ p[l]) <= 0 && (p[i] * p[l]) < 0) {
            ++l;
        }
        if ((p[i] ^ p[k]) == 0 && (p[i] * p[k]) < 0) {
            if (k - i > 1 && i + n - k > 1) {
                ans = min(ans, p[i].c + p[k].c + seg.Query(1, 1, n * 2, i + 1, k - 1) + seg.Query(1, 1, n * 2, k + 1, i + n - 1));
            }
            if (k - j > 0 && l - k > 1) {
                ans = min(ans, p[i].c + seg.Query(1, 1, n * 2, j, k - 1) + seg.Query(1, 1, n * 2, k + 1, l - 1));
            }
        } else {
            if (k - j > 0 && l - k > 0) {
                ans = min(ans, p[i].c + seg.Query(1, 1, n * 2, j, k - 1) + seg.Query(1, 1, n * 2, k, l - 1));
            }
        }
    }
    if (ans == 1e18) printf("-1\n");
    else printf("%lld\n", ans);
}

int main() {
    solve();
    return 0;
}
accuracy: 0.0872093023255814
time_ms: 100
memory_kb: 23152
final_rank: 17

code_snippet: #include <bits/stdc++.h>
#define lc (rt << 1)
#define rc (rt << 1) | 1
using namespace std;
typedef long long LL;
typedef long double LD;
const int MAXN = 400005;
const LD PI = acosl(-1.0);

int n;

struct Ticket {
    LL x, y;
    LL c;
    LL operator * (const Ticket &rhs) const {
        return x * rhs.x + y * rhs.y;
    }
    LL operator ^ (const Ticket &rhs) const {
        return x * rhs.y - y * rhs.x;
    }
} p[MAXN];

bool polar_cmp(Ticket a, Ticket b) {
    int da = (a.y > 0 || (a.y == 0 && a.x > 0));
    int db = (b.y > 0 || (b.y == 0 && b.x > 0));
    if (da != db) return da < db;
    if ((a ^ b) != 0) return (a ^ b) > 0;
    return a.c < b.c;
}

struct SegmentTree {
    LL mn[MAXN << 2];
    void Build(int rt, int b, int e) {\
        if (b == e) {
            mn[rt] = p[b].c;
            return;
        }
        int mid = (b + e) >> 1;
        Build(lc, b, mid);
        Build(rc, mid + 1, e);
        mn[rt] = min(mn[lc], mn[rc]);
    }
    LL Query(int rt, int b, int e, int l, int r) {
        if (l <= b && e <= r) return mn[rt];
        int mid = (b + e) >> 1;
        if (r <= mid) return Query(lc, b, mid, l, r);
        if (l > mid) return Query(rc, mid + 1, e, l, r);
        return min(Query(lc, b, mid, l, r), Query(rc, mid + 1, e, l, r));
    }
} seg;

void solve() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%lld %lld %lld", &p[i].x, &p[i].y, &p[i].c);
        if (!p[i].x && !p[i].y) {
            --i; --n;
        }
    }
    sort(p + 1, p + n + 1, polar_cmp);
    int m = 0;
    for (int i = 1; i <= n; ++i) {
        if (i == 1 || (p[i] ^ p[m]) != 0 && (p[i] * p[m]) < 0) {
            p[++m] = p[i];
        }
    }
    n = m;
    for (int i = 1; i <= n; ++i) {
        p[n + i] = p[i];
    }
    seg.Build(1, 1, n * 2);
    LL ans = 1e18;
    for (int i = 1, j = 0, k = 0, l = 0; i <= n; ++i) {
        j = max(j, i + 1);
        while (j < i + n && (p[i] ^ p[j]) > 0 && (p[i] * p[j]) > 0) {
            ++j;
        }
        k = max(k, j);
        while (k < i + n && (p[i] ^ p[k]) > 0) {
            ++k;
        }
        l = max(l, k);
        while (l < i + n && (p[i] ^ p[l]) < 0 && (p[i] * p[l]) < 0) {
            ++l;
        }
        if ((p[i] ^ p[k]) == 0 && (p[i] * p[k]) < 0) {
            if (k - i > 1 && i + n - k > 1) {
                ans = min(ans, p[i].c + p[k].c + seg.Query(1, 1, n * 2, i + 1, k - 1) + seg.Query(1, 1, n * 2, k + 1, i + n - 1));
            }
        } else {
            if (k - j > 0 && l - k > 0) {
                ans = min(ans, p[i].c + seg.Query(1, 1, n * 2, j, k - 1) + seg.Query(1, 1, n * 2, k, l - 1));
            }
        }
    }
    if (ans == 1e18) printf("-1\n");
    else printf("%lld\n", ans);
}

int main() {
    solve();
    return 0;
}
accuracy: 0.011627906976744186
time_ms: 50
memory_kb: 9652
final_rank: 19

code_snippet: #line 1 "f.cpp"
// cSpell:disable
/*	author:  Kite_kuma
	created: 2022.09.14 01:43:54 */

#line 2 "SPJ-Library/template/kuma.hpp"

#line 2 "SPJ-Library/template/basic_func.hpp"

#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool flag = true) { std::cout << (flag ? "Yes" : "No") << '\n'; }
void YES(bool flag = true) { std::cout << (flag ? "YES" : "NO") << '\n'; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(const T &x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(const Head &H, const Tail &... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T value) {
	for(auto &a : v) a += value;
	return;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

// ceil(a / b);
template <class T>
T dup(T a, T b) {
	assert(b);
	if(b < 0) {
		a *= -1;
		b *= -1;
	}
	return least_upper_multiple(a, b) / b;
}

long long pow_ll(long long a, long long n) {
	assert(n >= 0LL);
	if(n == 0) return 1LL;
	if(a == 0) return 0LL;
	if(a == 1) return 1LL;
	if(a == -1) return (n & 1LL) ? -1LL : 1LL;
	long long res = 1;
	while(n > 1LL) {
		if(n & 1LL) res *= a;
		a *= a;
		n >>= 1;
	}
	return res * a;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, const long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return (int)std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return (int)std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(const std::vector<T> &a) {
	std::vector<T> vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(const auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}
#line 1 "SPJ-Library/template/header.hpp"
#include <bits/stdc++.h>
#line 2 "SPJ-Library/template/io.hpp"

#line 4 "SPJ-Library/template/io.hpp"

#line 8 "SPJ-Library/template/debug.hpp"

#line 3 "SPJ-Library/template/constants.hpp"

constexpr int inf = 1000'000'000;
constexpr long long INF = 1'000'000'000'000'000'000LL;
constexpr int mod_1000000007 = 1000000007;
constexpr int mod_998244353 = 998244353;
const long double pi = acosl(-1.);
constexpr int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
constexpr int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
#line 10 "SPJ-Library/template/debug.hpp"

namespace viewer {

template <typename T, typename U>
void view(const std::pair<T, U> &p);

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p);

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p);

void view(const long long &e);

void view(const int &e);

template <typename T>
void view(const T &e);

template <typename T>
void view(const std::set<T> &s);

template <typename T>
void view(const std::unordered_set<T> &s);

template <typename T>
void view(const std::multiset<T> &s);

template <typename T>
void view(const std::unordered_multiset<T> &s);

template <typename T>
void view(const std::vector<T> &v);

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v);

template <typename T>
void view(const std::vector<std::vector<T>> &vv);

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v);

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v);

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v);

template <typename map_type>
void view_map_container(const map_type &m);

template <typename T, typename U>
void view(const std::map<T, U> &m);

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m);

template <typename container_type>
void view_container(const container_type &c, bool vertically = false) {
	typename container_type::const_iterator begin = c.begin();
	const typename container_type::const_iterator end = c.end();
	if(vertically) {
		std::cerr << "{\n";
		while(begin != end) {
			std::cerr << '\t';
			view(*(begin++));
			if(begin != end) std::cerr << ',';
			std::cerr << '\n';
		}
		std::cerr << '}';
		return;
	}
	std::cerr << "{ ";
	while(begin != end) {
		view(*(begin++));
		if(begin != end) std::cerr << ',';
		std::cerr << ' ';
	}
	std::cerr << '}';
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << '(';
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ')';
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ')';
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ')';
}

void view(const long long &e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int &e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T &e) {
	std::cerr << e;
}

template <typename T>
void view(const std::set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::vector<T> &v) {
	view_container(v);
}

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v) {
	view_container(v);
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	view_container(vv, true);
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	view_container(v, true);
}

template <typename map_type>
void view_map_container(const map_type &m) {
	std::cerr << "{\n";
	for(typename map_type::const_iterator it = m.begin(); it != m.end(); it++) {
		std::cerr << "\t[";
		view(it->first);
		std::cerr << "] : ";
		view(it->second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	view_map_container(m);
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	view_map_container(m);
}

}  // namespace viewer

// when compiling : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename T>
void debug_out(const T &x) {
	viewer::view(x);
}
template <typename Head, typename... Tail>
void debug_out(const Head &H, const Tail &... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "]\n";                                       \
	} while(0)
#else
#define debug(...) (void(0))
#endif
#line 2 "SPJ-Library/template/scanner.hpp"

#line 6 "SPJ-Library/template/scanner.hpp"

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner
#line 7 "SPJ-Library/template/io.hpp"

#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}

template <typename T1, typename T2>
std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << ' ' << p.second;
	return os;
}

struct fast_io {
	fast_io() {
		std::ios::sync_with_stdio(false);
		std::cin.tie(nullptr);
		std::cout << std::fixed << std::setprecision(15);
		srand((unsigned)time(NULL));
	}
} fast_io_;
#line 2 "SPJ-Library/template/macros.hpp"

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define pcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))
#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;
#line 7 "SPJ-Library/template/kuma.hpp"

using namespace std;
#line 6 "f.cpp"

// floor(atan2(y, x) / (pi / 2))
// atan2(y, x) \in [0, pi * 2)
int quadrant(ll x, ll y) {
	assert(x || y);
	if(x == 0) return y > 0 ? 1 : 3;
	if(x > 0) return y >= 0 ? 0 : 3;
	return y > 0 ? 1 : 2;
}

using pt = pair<ll, ll>;
bool ccw(pt a, pt b) { return a.first * b.second - a.second * b.first > 0; }

auto compare = [](pt a, pt b) -> bool {
	int qa = quadrant(a.first, a.second);
	int qb = quadrant(b.first, b.second);
	return qa == qb ? ccw(a, b) : qa < qb;
};
auto is_equal = [](pt a, pt b) -> bool { return !compare(a, b) && !compare(b, a); };

ll solve(int n, vector<pair<pt, ll>> dirs) {
	ll ans = INF;

	vector<pair<ll, int>> prices;
	{
		auto tmp = dirs;
		dirs.clear();
		for(auto [xy, price] : tmp) {
			if(dirs.size() && is_equal(dirs.back().first, xy)) continue;
			prices.emplace_back(price, int(dirs.size()));
			dirs.emplace_back(xy, price);
		}
	}
	if(int(dirs.size()) < 3) return INF;
	sort(all(prices));
	debug(dirs);
	debug(prices);
	auto ccw = [&](pt a, pt b) { return a.first * b.second - a.second * b.first > 0; };
	rep(use_candidate, min(100, (int)prices.size())) {
		const int idx = prices.at(use_candidate).second;
		rotate(dirs.begin(), dirs.begin() + idx, dirs.end());

		auto mid = dirs.begin() + 1;
		while(mid != dirs.end() && !ccw(mid->first, dirs.front().first)) mid++;
		if(mid == dirs.end()) continue;

		ll third = INF;
		const ll first_value = dirs.front().second;

		for(auto second_itr = dirs.begin() + 1; second_itr != dirs.end() && ccw(dirs.front().first, second_itr->first); second_itr++) {
			while(mid != dirs.end() && ccw(second_itr->first, mid->first)) {
				chmin(third, mid->second);
				mid++;
			}
			chmin(ans, first_value + second_itr->second + third);
		}

		rotate(dirs.begin(), dirs.end() - idx, dirs.end());
	}

	vll opponents;
	auto mid = dirs.begin() + 1;
	for(auto smaller = dirs.begin(); mid != dirs.end(); smaller++) {
		while(mid != dirs.end() && ccw(smaller->first, mid->first)) mid++;
		debug(smaller - dirs.begin(), mid - dirs.begin());
		if(mid != dirs.end() && is_equal(smaller->first, pair(-(mid->first.first), -(mid->first.second)))) {
			debug(smaller - dirs.begin(), smaller->first, mid->first);
			opponents.push_back(mid->second + smaller->second);
		}
	}
	sort(all(opponents));
	debug(opponents);
	if(int(opponents.size()) >= 2) chmin(ans, opponents[0] + opponents[1]);

	return ans;
}

ll naive(int n, vector<pair<pt, ll>> dirs) {
	ll ret = INF;
	rep(i, n) rep(j, i + 1, n) {
		if(!ccw(dirs[i].first, dirs[j].first)) break;
		rep(k, j + 1, n) {
			if(!ccw(dirs[j].first, dirs[k].first)) break;
			ll value = dirs[i].second + dirs[j].second + dirs[k].second;
			if(ccw(dirs[k].first, dirs[i].first)) {
				if(chmin(ret, value)) {
					debug(i, j, k);
				}
			} else {
				rep(m, k + 1, n) {
					if(ccw(dirs[k].first, dirs[m].first) && ccw(dirs[m].first, dirs[i].first)) {
						if(chmin(ret, value + dirs[m].second)) {
							debug(i, j, k, m);
						}
					}
				}
			}
		}
	}
	debug(dirs);
	return ret;
}

int main() {
	int n;
	while(cin >> n && n) {
		vector<pair<pt, ll>> dirs;
		rep(n) {
			LL(a, b, price);
			if(abs(a) + abs(b) == 0) continue;
			dirs.emplace_back(pt(a, b), price);
		}
		sort(all(dirs), [&](const pair<pt, ll> &a, const pair<pt, ll> &b) {
			if(is_equal(a.first, b.first)) return a.second < b.second;
			return compare(a.first, b.first);
		});
		ll res = solve(n, dirs);
#ifdef LOCAL
		ll ans = naive(n, dirs);
		debug(res, ans);
		assert(res == ans);
#endif
		cout << (res == INF ? -1 : res) << '\n';
	}
	return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 25656
final_rank: 3

code_snippet: #line 1 "f.cpp"
// cSpell:disable
/*	author:  Kite_kuma
	created: 2022.09.14 01:43:54 */

#line 2 "SPJ-Library/template/kuma.hpp"

#line 2 "SPJ-Library/template/basic_func.hpp"

#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool flag = true) { std::cout << (flag ? "Yes" : "No") << '\n'; }
void YES(bool flag = true) { std::cout << (flag ? "YES" : "NO") << '\n'; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(const T &x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(const Head &H, const Tail &... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T value) {
	for(auto &a : v) a += value;
	return;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

// ceil(a / b);
template <class T>
T dup(T a, T b) {
	assert(b);
	if(b < 0) {
		a *= -1;
		b *= -1;
	}
	return least_upper_multiple(a, b) / b;
}

long long pow_ll(long long a, long long n) {
	assert(n >= 0LL);
	if(n == 0) return 1LL;
	if(a == 0) return 0LL;
	if(a == 1) return 1LL;
	if(a == -1) return (n & 1LL) ? -1LL : 1LL;
	long long res = 1;
	while(n > 1LL) {
		if(n & 1LL) res *= a;
		a *= a;
		n >>= 1;
	}
	return res * a;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, const long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return (int)std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return (int)std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(const std::vector<T> &a) {
	std::vector<T> vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(const auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}
#line 1 "SPJ-Library/template/header.hpp"
#include <bits/stdc++.h>
#line 2 "SPJ-Library/template/io.hpp"

#line 4 "SPJ-Library/template/io.hpp"

#line 8 "SPJ-Library/template/debug.hpp"

#line 3 "SPJ-Library/template/constants.hpp"

constexpr int inf = 1000'000'000;
constexpr long long INF = 1'000'000'000'000'000'000LL;
constexpr int mod_1000000007 = 1000000007;
constexpr int mod_998244353 = 998244353;
const long double pi = acosl(-1.);
constexpr int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
constexpr int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
#line 10 "SPJ-Library/template/debug.hpp"

namespace viewer {

template <typename T, typename U>
void view(const std::pair<T, U> &p);

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p);

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p);

void view(const long long &e);

void view(const int &e);

template <typename T>
void view(const T &e);

template <typename T>
void view(const std::set<T> &s);

template <typename T>
void view(const std::unordered_set<T> &s);

template <typename T>
void view(const std::multiset<T> &s);

template <typename T>
void view(const std::unordered_multiset<T> &s);

template <typename T>
void view(const std::vector<T> &v);

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v);

template <typename T>
void view(const std::vector<std::vector<T>> &vv);

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v);

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v);

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v);

template <typename map_type>
void view_map_container(const map_type &m);

template <typename T, typename U>
void view(const std::map<T, U> &m);

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m);

template <typename container_type>
void view_container(const container_type &c, bool vertically = false) {
	typename container_type::const_iterator begin = c.begin();
	const typename container_type::const_iterator end = c.end();
	if(vertically) {
		std::cerr << "{\n";
		while(begin != end) {
			std::cerr << '\t';
			view(*(begin++));
			if(begin != end) std::cerr << ',';
			std::cerr << '\n';
		}
		std::cerr << '}';
		return;
	}
	std::cerr << "{ ";
	while(begin != end) {
		view(*(begin++));
		if(begin != end) std::cerr << ',';
		std::cerr << ' ';
	}
	std::cerr << '}';
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << '(';
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ')';
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ')';
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ')';
}

void view(const long long &e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int &e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T &e) {
	std::cerr << e;
}

template <typename T>
void view(const std::set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::vector<T> &v) {
	view_container(v);
}

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v) {
	view_container(v);
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	view_container(vv, true);
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	view_container(v, true);
}

template <typename map_type>
void view_map_container(const map_type &m) {
	std::cerr << "{\n";
	for(typename map_type::const_iterator it = m.begin(); it != m.end(); it++) {
		std::cerr << "\t[";
		view(it->first);
		std::cerr << "] : ";
		view(it->second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	view_map_container(m);
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	view_map_container(m);
}

}  // namespace viewer

// when compiling : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename T>
void debug_out(const T &x) {
	viewer::view(x);
}
template <typename Head, typename... Tail>
void debug_out(const Head &H, const Tail &... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "]\n";                                       \
	} while(0)
#else
#define debug(...) (void(0))
#endif
#line 2 "SPJ-Library/template/scanner.hpp"

#line 6 "SPJ-Library/template/scanner.hpp"

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner
#line 7 "SPJ-Library/template/io.hpp"

#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}

template <typename T1, typename T2>
std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << ' ' << p.second;
	return os;
}

struct fast_io {
	fast_io() {
		std::ios::sync_with_stdio(false);
		std::cin.tie(nullptr);
		std::cout << std::fixed << std::setprecision(15);
		srand((unsigned)time(NULL));
	}
} fast_io_;
#line 2 "SPJ-Library/template/macros.hpp"

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define pcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))
#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;
#line 7 "SPJ-Library/template/kuma.hpp"

using namespace std;
#line 6 "f.cpp"

// floor(atan2(y, x) / (pi / 2))
// atan2(y, x) \in [0, pi * 2)
int quadrant(ll x, ll y) {
	assert(x || y);
	if(x == 0) return y > 0 ? 1 : 3;
	if(x > 0) return y >= 0 ? 0 : 3;
	return y > 0 ? 1 : 2;
}

int main() {
	int n;
	cin >> n;
	ll ans = INF;
	using pt = pair<ll, ll>;
	auto compare_angle = [&](pt a, pt b) -> bool {
		int qa = quadrant(a.first, a.second);
		int qb = quadrant(b.first, b.second);
		if(qa != qb) return qa < qb;
		return a.first * b.second - a.second * b.first > 0;
	};
	auto is_equal = [&](pt a, pt b) -> bool { return !compare_angle(a, b) && !compare_angle(b, a); };
	vector<pair<pt, ll>> dirs;
	rep(n) {
		LL(a, b, price);
		if(abs(a) + abs(b) == 0) continue;
		dirs.emplace_back(pt(a, b), price);
	}
	sort(all(dirs), [&](const pair<pt, ll> &a, const pair<pt, ll> &b) {
		if(is_equal(a.first, b.first)) return a.second < b.second;
		return compare_angle(a.first, b.first);
	});
	vector<pair<ll, int>> prices;
	{
		auto tmp = dirs;
		dirs.clear();
		for(auto [xy, price] : tmp) {
			if(dirs.size() && is_equal(dirs.back().first, xy)) continue;
			prices.emplace_back(price, int(dirs.size()));
			dirs.emplace_back(xy, price);
		}
	}
	if(int(dirs.size()) < 3) drop(-1);
	sort(all(prices));
	debug(dirs);
	debug(prices);
	auto ccw = [&](pt a, pt b) { return a.first * b.second - a.second * b.first > 0; };
	rep(use_candidate, min(100, (int)prices.size())) {
		const int idx = prices.at(use_candidate).second;
		rotate(dirs.begin(), dirs.begin() + idx, dirs.end());

		auto mid = dirs.begin() + 1;
		while(mid != dirs.end() && !ccw(mid->first, dirs.front().first)) mid++;
		if(mid == dirs.end()) continue;

		ll third = INF;
		const ll first_value = dirs.front().second;

		for(auto second_itr = dirs.begin() + 1; second_itr != dirs.end() && ccw(dirs.front().first, second_itr->first); second_itr++) {
			while(mid != dirs.end() && ccw(second_itr->first, mid->first)) {
				chmin(third, mid->second);
				mid++;
			}
			chmin(ans, first_value + second_itr->second + third);
		}

		rotate(dirs.begin(), dirs.end() - idx, dirs.end());
	}

	vll opponents;
	auto mid = dirs.begin() + 1;
	for(auto smaller = dirs.begin(); mid != dirs.end(); smaller++) {
		while(mid != dirs.end() && ccw(smaller->first, mid->first)) mid++;
		if(mid != dirs.end() && is_equal(smaller->first, mid->first)) {
			opponents.push_back(mid->second + smaller->second);
		}
	}
	sort(all(opponents));
	if(int(opponents.size()) >= 2) chmin(ans, opponents[0] + opponents[1]);

	if(ans >= INF) ans = -1;
	drop(ans);

	return 0;
}
accuracy: 0.7965116279069767
time_ms: 230
memory_kb: 21572
final_rank: 12

code_snippet: #line 1 "f.cpp"
// cSpell:disable
/*	author:  Kite_kuma
	created: 2022.09.14 01:43:54 */

#line 2 "SPJ-Library/template/kuma.hpp"

#line 2 "SPJ-Library/template/basic_func.hpp"

#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool flag = true) { std::cout << (flag ? "Yes" : "No") << '\n'; }
void YES(bool flag = true) { std::cout << (flag ? "YES" : "NO") << '\n'; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(const T &x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(const Head &H, const Tail &... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T value) {
	for(auto &a : v) a += value;
	return;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

// ceil(a / b);
template <class T>
T dup(T a, T b) {
	assert(b);
	if(b < 0) {
		a *= -1;
		b *= -1;
	}
	return least_upper_multiple(a, b) / b;
}

long long pow_ll(long long a, long long n) {
	assert(n >= 0LL);
	if(n == 0) return 1LL;
	if(a == 0) return 0LL;
	if(a == 1) return 1LL;
	if(a == -1) return (n & 1LL) ? -1LL : 1LL;
	long long res = 1;
	while(n > 1LL) {
		if(n & 1LL) res *= a;
		a *= a;
		n >>= 1;
	}
	return res * a;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, const long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return (int)std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return (int)std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(const std::vector<T> &a) {
	std::vector<T> vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(const auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}
#line 1 "SPJ-Library/template/header.hpp"
#include <bits/stdc++.h>
#line 2 "SPJ-Library/template/io.hpp"

#line 4 "SPJ-Library/template/io.hpp"

#line 8 "SPJ-Library/template/debug.hpp"

#line 3 "SPJ-Library/template/constants.hpp"

constexpr int inf = 1000'000'000;
constexpr long long INF = 1'000'000'000'000'000'000LL;
constexpr int mod_1000000007 = 1000000007;
constexpr int mod_998244353 = 998244353;
const long double pi = acosl(-1.);
constexpr int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
constexpr int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
#line 10 "SPJ-Library/template/debug.hpp"

namespace viewer {

template <typename T, typename U>
void view(const std::pair<T, U> &p);

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p);

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p);

void view(const long long &e);

void view(const int &e);

template <typename T>
void view(const T &e);

template <typename T>
void view(const std::set<T> &s);

template <typename T>
void view(const std::unordered_set<T> &s);

template <typename T>
void view(const std::multiset<T> &s);

template <typename T>
void view(const std::unordered_multiset<T> &s);

template <typename T>
void view(const std::vector<T> &v);

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v);

template <typename T>
void view(const std::vector<std::vector<T>> &vv);

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v);

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v);

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v);

template <typename map_type>
void view_map_container(const map_type &m);

template <typename T, typename U>
void view(const std::map<T, U> &m);

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m);

template <typename container_type>
void view_container(const container_type &c, bool vertically = false) {
	typename container_type::const_iterator begin = c.begin();
	const typename container_type::const_iterator end = c.end();
	if(vertically) {
		std::cerr << "{\n";
		while(begin != end) {
			std::cerr << '\t';
			view(*(begin++));
			if(begin != end) std::cerr << ',';
			std::cerr << '\n';
		}
		std::cerr << '}';
		return;
	}
	std::cerr << "{ ";
	while(begin != end) {
		view(*(begin++));
		if(begin != end) std::cerr << ',';
		std::cerr << ' ';
	}
	std::cerr << '}';
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << '(';
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ')';
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ')';
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ')';
}

void view(const long long &e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int &e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T &e) {
	std::cerr << e;
}

template <typename T>
void view(const std::set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::vector<T> &v) {
	view_container(v);
}

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v) {
	view_container(v);
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	view_container(vv, true);
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	view_container(v, true);
}

template <typename map_type>
void view_map_container(const map_type &m) {
	std::cerr << "{\n";
	for(typename map_type::const_iterator it = m.begin(); it != m.end(); it++) {
		std::cerr << "\t[";
		view(it->first);
		std::cerr << "] : ";
		view(it->second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	view_map_container(m);
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	view_map_container(m);
}

}  // namespace viewer

// when compiling : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename T>
void debug_out(const T &x) {
	viewer::view(x);
}
template <typename Head, typename... Tail>
void debug_out(const Head &H, const Tail &... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "]\n";                                       \
	} while(0)
#else
#define debug(...) (void(0))
#endif
#line 2 "SPJ-Library/template/scanner.hpp"

#line 6 "SPJ-Library/template/scanner.hpp"

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner
#line 7 "SPJ-Library/template/io.hpp"

#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}

template <typename T1, typename T2>
std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << ' ' << p.second;
	return os;
}

struct fast_io {
	fast_io() {
		std::ios::sync_with_stdio(false);
		std::cin.tie(nullptr);
		std::cout << std::fixed << std::setprecision(15);
		srand((unsigned)time(NULL));
	}
} fast_io_;
#line 2 "SPJ-Library/template/macros.hpp"

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define pcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))
#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;
#line 7 "SPJ-Library/template/kuma.hpp"

using namespace std;
#line 6 "f.cpp"

// floor(atan2(y, x) / (pi / 2))
// atan2(y, x) \in [0, pi * 2)
int quadrant(ll x, ll y) {
	assert(x || y);
	if(x == 0) return y > 0 ? 1 : 3;
	if(x > 0) return y >= 0 ? 0 : 3;
	return y > 0 ? 1 : 2;
}

int main() {
	int n;
	cin >> n;
	ll ans = INF;
	using pt = pair<ll, ll>;
	auto compare_angle = [&](pt a, pt b) -> bool {
		int qa = quadrant(a.first, a.second);
		int qb = quadrant(b.first, b.second);
		if(qa != qb) return qa < qb;
		return a.first * b.second - a.second * b.first > 0;
	};
	auto is_equal = [&](pt a, pt b) -> bool { return !compare_angle(a, b) && !compare_angle(b, a); };
	vector<pair<pt, ll>> dirs;
	rep(n) {
		LL(a, b, price);
		if(abs(a) + abs(b) == 0) continue;
		dirs.emplace_back(pt(a, b), price);
	}
	sort(all(dirs), [&](const pair<pt, ll> &a, const pair<pt, ll> &b) {
		if(is_equal(a.first, b.first)) return a.second < b.second;
		return compare_angle(a.first, b.first);
	});
	vector<pair<ll, int>> prices;
	{
		auto tmp = dirs;
		dirs.clear();
		for(auto [xy, price] : tmp) {
			if(dirs.size() && is_equal(dirs.back().first, xy)) continue;
			prices.emplace_back(price, int(dirs.size()));
			dirs.emplace_back(xy, price);
		}
	}
	if(int(dirs.size()) < 3) drop(-1);
	sort(all(prices));
	debug(dirs);
	debug(prices);
	auto ccw = [&](pt a, pt b) { return a.first * b.second - a.second * b.first > 0; };
	rep(use_candidate, min(10, (int)prices.size())) {
		const int idx = prices.at(use_candidate).second;
		rotate(dirs.begin(), dirs.begin() + idx, dirs.end());

		auto mid = dirs.begin() + 1;
		while(mid != dirs.end() && !ccw(mid->first, dirs.front().first)) mid++;
		if(mid == dirs.end()) continue;

		ll third = INF;
		const ll first_value = dirs.front().second;

		for(auto second_itr = dirs.begin() + 1; second_itr != dirs.end() && ccw(dirs.front().first, second_itr->first); second_itr++) {
			while(mid != dirs.end() && ccw(second_itr->first, mid->first)) {
				chmin(third, mid->second);
				mid++;
			}
			chmin(ans, first_value + second_itr->second + third);
		}

		rotate(dirs.begin(), dirs.end() - idx, dirs.end());
	}

	vll opponents;
	auto mid = dirs.begin() + 1;
	for(auto smaller = dirs.begin(); mid != dirs.end(); smaller++) {
		while(mid != dirs.end() && ccw(smaller->first, mid->first)) mid++;
		if(mid != dirs.end() && is_equal(smaller->first, mid->first)) {
			opponents.push_back(mid->second + smaller->second);
		}
	}
	sort(all(opponents));
	if(int(opponents.size()) >= 2) chmin(ans, opponents[0] + opponents[1]);

	if(ans >= INF) ans = -1;
	drop(ans);

	return 0;
}
accuracy: 0.7965116279069767
time_ms: 90
memory_kb: 21132
final_rank: 10

code_snippet: #line 1 "f.cpp"
// cSpell:disable
/*	author:  Kite_kuma
	created: 2022.09.14 01:43:54 */

#line 2 "SPJ-Library/template/kuma.hpp"

#line 2 "SPJ-Library/template/basic_func.hpp"

#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool flag = true) { std::cout << (flag ? "Yes" : "No") << '\n'; }
void YES(bool flag = true) { std::cout << (flag ? "YES" : "NO") << '\n'; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(const T &x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(const Head &H, const Tail &... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T value) {
	for(auto &a : v) a += value;
	return;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

// ceil(a / b);
template <class T>
T dup(T a, T b) {
	assert(b);
	if(b < 0) {
		a *= -1;
		b *= -1;
	}
	return least_upper_multiple(a, b) / b;
}

long long pow_ll(long long a, long long n) {
	assert(n >= 0LL);
	if(n == 0) return 1LL;
	if(a == 0) return 0LL;
	if(a == 1) return 1LL;
	if(a == -1) return (n & 1LL) ? -1LL : 1LL;
	long long res = 1;
	while(n > 1LL) {
		if(n & 1LL) res *= a;
		a *= a;
		n >>= 1;
	}
	return res * a;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, const long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return (int)std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return (int)std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(const std::vector<T> &a) {
	std::vector<T> vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(const auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}
#line 1 "SPJ-Library/template/header.hpp"
#include <bits/stdc++.h>
#line 2 "SPJ-Library/template/io.hpp"

#line 4 "SPJ-Library/template/io.hpp"

#line 8 "SPJ-Library/template/debug.hpp"

#line 3 "SPJ-Library/template/constants.hpp"

constexpr int inf = 1000'000'000;
constexpr long long INF = 1'000'000'000'000'000'000LL;
constexpr int mod_1000000007 = 1000000007;
constexpr int mod_998244353 = 998244353;
const long double pi = acosl(-1.);
constexpr int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
constexpr int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
#line 10 "SPJ-Library/template/debug.hpp"

namespace viewer {

template <typename T, typename U>
void view(const std::pair<T, U> &p);

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p);

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p);

void view(const long long &e);

void view(const int &e);

template <typename T>
void view(const T &e);

template <typename T>
void view(const std::set<T> &s);

template <typename T>
void view(const std::unordered_set<T> &s);

template <typename T>
void view(const std::multiset<T> &s);

template <typename T>
void view(const std::unordered_multiset<T> &s);

template <typename T>
void view(const std::vector<T> &v);

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v);

template <typename T>
void view(const std::vector<std::vector<T>> &vv);

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v);

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v);

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v);

template <typename map_type>
void view_map_container(const map_type &m);

template <typename T, typename U>
void view(const std::map<T, U> &m);

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m);

template <typename container_type>
void view_container(const container_type &c, bool vertically = false) {
	typename container_type::const_iterator begin = c.begin();
	const typename container_type::const_iterator end = c.end();
	if(vertically) {
		std::cerr << "{\n";
		while(begin != end) {
			std::cerr << '\t';
			view(*(begin++));
			if(begin != end) std::cerr << ',';
			std::cerr << '\n';
		}
		std::cerr << '}';
		return;
	}
	std::cerr << "{ ";
	while(begin != end) {
		view(*(begin++));
		if(begin != end) std::cerr << ',';
		std::cerr << ' ';
	}
	std::cerr << '}';
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << '(';
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ')';
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ')';
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ')';
}

void view(const long long &e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int &e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T &e) {
	std::cerr << e;
}

template <typename T>
void view(const std::set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::vector<T> &v) {
	view_container(v);
}

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v) {
	view_container(v);
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	view_container(vv, true);
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	view_container(v, true);
}

template <typename map_type>
void view_map_container(const map_type &m) {
	std::cerr << "{\n";
	for(typename map_type::const_iterator it = m.begin(); it != m.end(); it++) {
		std::cerr << "\t[";
		view(it->first);
		std::cerr << "] : ";
		view(it->second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	view_map_container(m);
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	view_map_container(m);
}

}  // namespace viewer

// when compiling : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename T>
void debug_out(const T &x) {
	viewer::view(x);
}
template <typename Head, typename... Tail>
void debug_out(const Head &H, const Tail &... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "]\n";                                       \
	} while(0)
#else
#define debug(...) (void(0))
#endif
#line 2 "SPJ-Library/template/scanner.hpp"

#line 6 "SPJ-Library/template/scanner.hpp"

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner
#line 7 "SPJ-Library/template/io.hpp"

#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}

template <typename T1, typename T2>
std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << ' ' << p.second;
	return os;
}

struct fast_io {
	fast_io() {
		std::ios::sync_with_stdio(false);
		std::cin.tie(nullptr);
		std::cout << std::fixed << std::setprecision(15);
		srand((unsigned)time(NULL));
	}
} fast_io_;
#line 2 "SPJ-Library/template/macros.hpp"

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define pcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))
#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;
#line 7 "SPJ-Library/template/kuma.hpp"

using namespace std;
#line 6 "f.cpp"

// floor(atan2(y, x) / (pi / 2))
// atan2(y, x) \in [0, pi * 2)
int quadrant(ll x, ll y) {
	assert(x || y);
	if(x == 0) return y > 0 ? 1 : 3;
	if(x > 0) return y >= 0 ? 0 : 3;
	return y > 0 ? 1 : 2;
}

int main() {
	int n;
	cin >> n;
	ll ans = INF;
	using pt = pair<ll, ll>;
	auto compare_angle = [&](pt a, pt b) -> bool {
		int qa = quadrant(a.first, a.second);
		int qb = quadrant(b.first, b.second);
		if(qa != qb) return qa < qb;
		return a.first * b.second - a.second * b.first > 0;
	};
	auto is_equal = [&](pt a, pt b) -> bool { return !compare_angle(a, b) && !compare_angle(b, a); };
	vector<pair<pt, ll>> dirs;
	rep(n) {
		LL(a, b, price);
		if(abs(a) + abs(b) == 0) continue;
		dirs.emplace_back(pt(a, b), price);
	}
	sort(all(dirs), [&](const pair<pt, ll> &a, const pair<pt, ll> &b) {
		if(is_equal(a.first, b.first)) return a.second < b.second;
		return compare_angle(a.first, b.first);
	});
	vector<pair<ll, int>> prices;
	{
		auto tmp = dirs;
		dirs.clear();
		for(auto [xy, price] : tmp) {
			if(dirs.size() && is_equal(dirs.back().first, xy)) continue;
			prices.emplace_back(price, int(dirs.size()));
			dirs.emplace_back(xy, price);
		}
	}
	sort(all(prices));
	debug(dirs);
	debug(prices);
	auto ccw = [&](pt a, pt b) { return a.first * b.second - a.second * b.first > 0; };
	rep(use_candidate, min(10, (int)prices.size())) {
		const int idx = prices.at(use_candidate).second;
		rotate(dirs.begin(), dirs.begin() + idx, dirs.end());

		auto mid = dirs.begin() + 1;
		while(mid != dirs.end() && !ccw(mid->first, dirs.front().first)) mid++;
		if(mid == dirs.end()) continue;

		ll third = INF;
		const ll first_value = dirs.front().second;

		for(auto second_itr = dirs.begin() + 1; second_itr != dirs.end() && ccw(dirs.front().first, second_itr->first); second_itr++) {
			while(mid != dirs.end() && ccw(second_itr->first, mid->first)) {
				chmin(third, mid->second);
				mid++;
			}
			chmin(ans, first_value + second_itr->second + third);
		}

		rotate(dirs.begin(), dirs.end() - idx, dirs.end());
	}

	vll opponents;
	auto mid = dirs.begin() + 1;
	for(auto smaller = dirs.begin(); mid != dirs.end(); smaller++) {
		while(mid != dirs.end() && ccw(smaller->first, mid->first)) mid++;
		if(mid != dirs.end() && is_equal(smaller->first, mid->first)) {
			opponents.push_back(mid->second + smaller->second);
		}
	}
	sort(all(opponents));
	if(int(opponents.size()) >= 2) chmin(ans, opponents[0] + opponents[1]);

	if(ans >= INF) ans = -1;
	drop(ans);

	return 0;
}
accuracy: 0.0872093023255814
time_ms: 90
memory_kb: 20616
final_rank: 16

code_snippet: #line 1 "f.cpp"
// cSpell:disable
/*	author:  Kite_kuma
	created: 2022.09.14 01:43:54 */

#line 2 "SPJ-Library/template/kuma.hpp"

#line 2 "SPJ-Library/template/basic_func.hpp"

#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool flag = true) { std::cout << (flag ? "Yes" : "No") << '\n'; }
void YES(bool flag = true) { std::cout << (flag ? "YES" : "NO") << '\n'; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(const T &x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(const Head &H, const Tail &... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T value) {
	for(auto &a : v) a += value;
	return;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

// ceil(a / b);
template <class T>
T dup(T a, T b) {
	assert(b);
	if(b < 0) {
		a *= -1;
		b *= -1;
	}
	return least_upper_multiple(a, b) / b;
}

long long pow_ll(long long a, long long n) {
	assert(n >= 0LL);
	if(n == 0) return 1LL;
	if(a == 0) return 0LL;
	if(a == 1) return 1LL;
	if(a == -1) return (n & 1LL) ? -1LL : 1LL;
	long long res = 1;
	while(n > 1LL) {
		if(n & 1LL) res *= a;
		a *= a;
		n >>= 1;
	}
	return res * a;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, const long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return (int)std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return (int)std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(const std::vector<T> &a) {
	std::vector<T> vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(const auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}
#line 1 "SPJ-Library/template/header.hpp"
#include <bits/stdc++.h>
#line 2 "SPJ-Library/template/io.hpp"

#line 4 "SPJ-Library/template/io.hpp"

#line 8 "SPJ-Library/template/debug.hpp"

#line 3 "SPJ-Library/template/constants.hpp"

constexpr int inf = 1000'000'000;
constexpr long long INF = 1'000'000'000'000'000'000LL;
constexpr int mod_1000000007 = 1000000007;
constexpr int mod_998244353 = 998244353;
const long double pi = acosl(-1.);
constexpr int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
constexpr int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
#line 10 "SPJ-Library/template/debug.hpp"

namespace viewer {

template <typename T, typename U>
void view(const std::pair<T, U> &p);

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p);

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p);

void view(const long long &e);

void view(const int &e);

template <typename T>
void view(const T &e);

template <typename T>
void view(const std::set<T> &s);

template <typename T>
void view(const std::unordered_set<T> &s);

template <typename T>
void view(const std::multiset<T> &s);

template <typename T>
void view(const std::unordered_multiset<T> &s);

template <typename T>
void view(const std::vector<T> &v);

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v);

template <typename T>
void view(const std::vector<std::vector<T>> &vv);

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v);

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v);

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v);

template <typename map_type>
void view_map_container(const map_type &m);

template <typename T, typename U>
void view(const std::map<T, U> &m);

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m);

template <typename container_type>
void view_container(const container_type &c, bool vertically = false) {
	typename container_type::const_iterator begin = c.begin();
	const typename container_type::const_iterator end = c.end();
	if(vertically) {
		std::cerr << "{\n";
		while(begin != end) {
			std::cerr << '\t';
			view(*(begin++));
			if(begin != end) std::cerr << ',';
			std::cerr << '\n';
		}
		std::cerr << '}';
		return;
	}
	std::cerr << "{ ";
	while(begin != end) {
		view(*(begin++));
		if(begin != end) std::cerr << ',';
		std::cerr << ' ';
	}
	std::cerr << '}';
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << '(';
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ')';
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ')';
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ')';
}

void view(const long long &e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int &e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T &e) {
	std::cerr << e;
}

template <typename T>
void view(const std::set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::vector<T> &v) {
	view_container(v);
}

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v) {
	view_container(v);
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	view_container(vv, true);
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	view_container(v, true);
}

template <typename map_type>
void view_map_container(const map_type &m) {
	std::cerr << "{\n";
	for(typename map_type::const_iterator it = m.begin(); it != m.end(); it++) {
		std::cerr << "\t[";
		view(it->first);
		std::cerr << "] : ";
		view(it->second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	view_map_container(m);
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	view_map_container(m);
}

}  // namespace viewer

// when compiling : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename T>
void debug_out(const T &x) {
	viewer::view(x);
}
template <typename Head, typename... Tail>
void debug_out(const Head &H, const Tail &... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "]\n";                                       \
	} while(0)
#else
#define debug(...) (void(0))
#endif
#line 2 "SPJ-Library/template/scanner.hpp"

#line 6 "SPJ-Library/template/scanner.hpp"

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner
#line 7 "SPJ-Library/template/io.hpp"

#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}

template <typename T1, typename T2>
std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << ' ' << p.second;
	return os;
}

struct fast_io {
	fast_io() {
		std::ios::sync_with_stdio(false);
		std::cin.tie(nullptr);
		std::cout << std::fixed << std::setprecision(15);
		srand((unsigned)time(NULL));
	}
} fast_io_;
#line 2 "SPJ-Library/template/macros.hpp"

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define pcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))
#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;
#line 7 "SPJ-Library/template/kuma.hpp"

using namespace std;
#line 6 "f.cpp"

// floor(atan2(y, x) / (pi / 2))
// atan2(y, x) \in [0, pi * 2)
int quadrant(ll x, ll y) {
	assert(x || y);
	if(x == 0) return y > 0 ? 1 : 3;
	if(x > 0) return y >= 0 ? 0 : 3;
	return y > 0 ? 1 : 2;
}

int main() {
	int n;
	cin >> n;
	ll ans = INF;
	using pt = pair<ll, ll>;
	auto compare_angle = [&](pt a, pt b) -> bool {
		int qa = quadrant(a.first, a.second);
		int qb = quadrant(b.first, b.second);
		if(qa != qb) return qa < qb;
		return a.first * b.second - a.second * b.first > 0;
	};
	auto is_equal = [&](pt a, pt b) -> bool { return !compare_angle(a, b) && !compare_angle(b, a); };
	vector<pair<pt, ll>> dirs;
	rep(n) {
		LL(a, b, price);
		if(abs(a) + abs(b) == 0) continue;
		dirs.emplace_back(pt(a, b), price);
	}
	sort(all(dirs), [&](const pair<pt, ll> &a, const pair<pt, ll> &b) {
		if(is_equal(a.first, b.first)) return a.second < b.second;
		return compare_angle(a.first, b.first);
	});
	vector<pair<ll, int>> prices;
	{
		auto tmp = dirs;
		dirs.clear();
		for(auto [xy, price] : tmp) {
			if(dirs.size() && is_equal(dirs.back().first, xy)) continue;
			prices.emplace_back(price, int(dirs.size()));
			dirs.emplace_back(xy, price);
		}
	}
	sort(all(prices));
	auto ccw = [&](pt a, pt b) { return a.first * b.second - a.second * b.first > 0; };
	rep(use_candidate, min(10, (int)prices.size())) {
		const int idx = prices.at(use_candidate).second;
		rotate(dirs.begin(), dirs.begin() + idx, dirs.end());

		auto mid = dirs.begin() + 1;
		while(mid != dirs.end() && !ccw(mid->first, dirs.front().first)) mid++;
		if(mid == dirs.end()) continue;

		ll third = INF;
		const ll first_value = prices[idx].first;

		for(auto second_itr = dirs.begin() + 1; second_itr != dirs.end() && ccw(dirs.front().first, second_itr->first); second_itr++) {
			while(mid != dirs.end() && ccw(second_itr->first, mid->first)) {
				chmin(third, mid->second);
				mid++;
			}
			chmin(ans, first_value + second_itr->second + third);
		}

		rotate(dirs.begin(), dirs.end() - idx, dirs.end());
	}

	vll opponents;
	auto mid = dirs.begin() + 1;
	for(auto smaller = dirs.begin(); mid != dirs.end(); smaller++) {
		while(mid != dirs.end() && ccw(smaller->first, mid->first)) mid++;
		if(mid != dirs.end() && smaller->first.first * mid->first.second == smaller->first.second * mid->first.first) {
			opponents.push_back(mid->second + smaller->second);
		}
	}
	sort(all(opponents));
	if(int(opponents.size()) >= 2) chmin(ans, opponents[0] + opponents[1]);

	if(ans >= INF) ans = -1;
	drop(ans);

	return 0;
}
accuracy: 0.011627906976744186
time_ms: 50
memory_kb: 12700
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=1000000007,MAX=100005;
const ll INF=1LL<<60;

template<typename T>
struct SparseTable{
    using F=function<T(T,T)>;
    
    int n,logn;
    vector<vector<T>> dat;
    vector<int> loglen;
    F f;
    T ti;
    
    SparseTable(int n_,F f,T ti) :f(f),ti(ti){
        n=1;
        logn=1;
        while(n<n_){
            n*=2;
            logn++;
        }
        loglen.resize(n+3);
        n=n_;
        int j=0;
        for(int i=1;i<n+3;i++){
            loglen[i]=j;
            if(i+1>(1<<(j+1))) j++;
        }
        
        dat.resize(logn);
        
        for(int i=0;i<logn;i++){
            dat[i].assign(n+1,ti);
        }
    }
    
    void set(vector<T> &v){
        for(int j=0;j<n+1;j++){
            if(j<si(v)) dat[0][j]=v[j];
        }
    }
    
    void set(int j,T x){
        dat[0][j]=x;
    }
    
    void built(){
        for(int i=1;i<logn;i++){
            for(int j=0;j<n+1;j++){
                T vl=dat[i-1][j],vr;
                if(j+(1<<(i-1))>=n+1) vr=ti;
                else vr=dat[i-1][j+(1<<(i-1))];
                dat[i][j]=f(vl,vr);
            }
        }
    }
    
    T query(int l,int r){
        if(l>=r) return ti;
        T vl=dat[loglen[r-l]][l],vr=dat[loglen[r-l]][r-(1<<loglen[r-l])];
        return f(vl,vr);
    }
};

ll gcd(ll a,ll b){
    if(b==0) return a;
    return gcd(b,a%b);
}

bool compare(pair<pair<ll,ll>,ll> aa,pair<pair<ll,ll>,ll> bb){
    pair<ll,ll> a=aa.fi,b=bb.fi;
    int at,bt;
    if(a.se>0||(a.se==0&&a.fi>0)) at=0;
    else at=1;
    
    if(b.se>0||(b.se==0&&b.fi>0)) bt=0;
    else bt=1;
    
    if(at!=bt) return at<bt;
    return a.fi*b.se-a.se*b.fi>0;
}

//整数での偏角ソート [0,2pi)になる

ll dot(pair<ll,ll> a,pair<ll,ll> b){
    return a.fi*b.fi+a.se*b.se;
}

ll cross(pair<ll,ll> a,pair<ll,ll> b){
    return a.fi*b.se-a.se*b.fi;
}

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    int N;cin>>N;
    map<pair<ll,ll>,ll> MA;
    for(int i=0;i<N;i++){
        ll a,b,c;cin>>a>>b>>c;
        if(a==0&&b==0) continue;
        ll x=gcd(abs(a),abs(b));
        if(MA.count(mp(a/x,b/x))){
            chmin(MA[mp(a/x,b/x)],c);
        }else{
            MA[mp(a/x,b/x)]=c;
        }
    }
    
    if(si(MA)<=2){
        cout<<-1<<"\n";
        return 0;
    }
    
    ll ans=INF;
    
    vector<ll> op;
    
    for(auto a:MA){
        auto [x,y]=a.fi;
        if(MA.count(mp(-x,-y))&&mp(x,y)<mp(-x,-y)){
            op.push_back(MA[mp(x,y)]+MA[mp(-x,-y)]);
        }
    }
    
    sort(all(op));
    
    if(si(op)>=2){
        chmin(ans,op[0]+op[1]);
    }
    
    map<pair<ll,ll>,int> dic;
    
    vector<pair<pair<ll,ll>,ll>> P;
    for(auto a:MA) P.push_back(a);
    sort(all(P),compare);
    
    N=si(P);
    
    for(int i=0;i<N;i++){
        P.push_back(P[i]);
        dic[P[i].fi]=P[i].se;
    }
    
    SparseTable<ll> spa(si(P),[](ll a,ll b){return min(a,b);},INF);
    for(int i=0;i<si(P);i++){
        spa.set(i,P[i].se);
    }
    spa.built();
    
    auto pos=[&](int i,int j){
        if(i==j) return 0;
        if(i+N==j) return 5;
        pair<ll,ll> a=P[i].fi,b=P[j].fi;
        ll s=dot(a,b);
        ll t=cross(a,b);
        if(s>=0&&t>0) return 0;
        if(s<0&&t>0) return 1;
        if(s<0&&t==0) return 2;
        if(s<0&&t<0) return 3;
        if(s>=0) return 4;
        return -1;
    };
    
    int a=0,b=0,c=0,d=0;
    
    for(int i=0;i<N;i++){
        while(a<si(P)&&pos(i,a)<1) a++;
        while(b<si(P)&&pos(i,b)<2) b++;
        while(c<si(P)&&pos(i,c)<3) c++;
        while(d<si(P)&&pos(i,d)<4) d++;
        
        //cout<<i<<" "<<a<<" "<<b<<" "<<c<<" "<<d<<endl;
        
        ll x=spa.query(a,b),y=spa.query(c,d);
        chmin(ans,P[i].se+x+y);
    };
    
    
    if(ans==INF) cout<<-1<<"\n";
    else cout<<ans<<"\n";
}
accuracy: 1
time_ms: 280
memory_kb: 103812
final_rank: 7

code_snippet: #pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#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<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
#include<chrono>
using namespace std;

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

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;

#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;

template<typename T>
void chmin(T& a, T b) {
	a = min(a, b);
}
template<typename T>
void chmax(T& a, T b) {
	a = max(a, b);
}
template<typename T>
void cinarray(vector<T>& v) {
	rep(i, v.size())cin >> v[i];
}
template<typename T>
void coutarray(vector<T>& v) {
	rep(i, v.size()) {
		if (i > 0)cout << " "; cout << v[i];
	}
	cout << "\n";
}
ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	if (x == 0)return 0;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	int n;
	modint() :n(0) { ; }
	modint(ll m) {
		if (m < 0 || mod <= m) {
			m %= mod; if (m < 0)m += mod;
		}
		n = m;
	}
	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, ll 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)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 20;
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];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

ll gcd(ll a, ll b) {
	a = abs(a); b = abs(b);
	if (a < b)swap(a, b);
	while (b) {
		ll r = a % b; a = b; b = r;
	}
	return a;
}
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };

using mP = pair<modint, modint>;
//-----------------------------------

using speP = pair<ld, int>;
ll calc(vector<int> x, vector<int> y, vector<ll> p) {
	int n = x.size();
	vector<speP> vp;
	rep(i, n) {
		ld t = atan2l(y[i], x[i]);
		if (t <= 0) {
			vp.push_back({ atan2l(-y[i],-x[i]),-(i+1) });
		}
		else {
			vp.push_back({ t,i+1 });
		}
	}
	sort(all(vp));
	vector<ll> le(n + 1, INF);
	vector<ll> ri(n + 1, INF);
	rep(i, vp.size()) {
		int id = vp[i].second;
		le[i + 1] = le[i];
		if (id > 0) {
			id--;
			chmin(le[i + 1], p[id]);
		}
	}
	per(i, vp.size()) {
		int id = vp[i].second;
		ri[i] = ri[i + 1];
		if (id > 0) {
			id--;
			chmin(ri[i], p[id]);
		}
	}
	ll res = INF;
	rep(i, vp.size()) {
		int l = i;
		while (i + 1 < vp.size() && vp[i].first == vp[i + 1].first)i++;
		Rep1(j, l, i) {
			int id = vp[j].second;
			if (id < 0) {
				id = -id; id--;
				ll val = le[l] + ri[i + 1];
				chmin(res, val + p[id]);
			}
		}
	}
	return res;
}
void solve() {
	int n; cin >> n;
	vector<int> x(n), y(n);
	vector<ll> p(n);
	rep(i, n)cin >> x[i] >> y[i] >> p[i];
	//exclude (0,0)
	{
		vector<int> nx, ny;
		vector<ll> np;
		rep(i, n) {
			if (x[i] == 0 && y[i] == 0) {
				continue;
			}
			nx.push_back(x[i]);
			ny.push_back(y[i]);
			np.push_back(p[i]);
		}
		swap(x, nx); swap(y, ny); swap(p, np);
		n = x.size();
	}
	//exclude gcd
	rep(i, n) {
		int g = gcd(x[i], y[i]);
		x[i] /= g;
		y[i] /= g;
	}
	ll ans = calc(x, y, p);
	//cout << ans << "\n";
	rep(i, n) {
		x[i] *= -1;
		y[i] *= -1;
	}
	ans = min(ans, calc(x, y, p));
	map<P, ll> mp;
	rep(i, n) {
		P pp = { x[i],y[i] };
		if (mp.find(pp) == mp.end())mp[pp] = p[i];
		else mp[pp] = min(mp[pp], p[i]);
	}
	rep(i, n) {
		P pp = { x[i],y[i] };
		ll val = 0;
		rep(d, 4) {
			if (mp.find(pp) == mp.end())val += INF;
			else val += mp[pp];
			swap(pp.first, pp.second);
			pp.first *= -1;
		}
		chmin(ans, val);
	}
	if (ans == INF)ans = -1;
	cout << ans << "\n";
}


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

code_snippet: #pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#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<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
#include<chrono>
using namespace std;

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

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;

#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;

template<typename T>
void chmin(T& a, T b) {
	a = min(a, b);
}
template<typename T>
void chmax(T& a, T b) {
	a = max(a, b);
}
template<typename T>
void cinarray(vector<T>& v) {
	rep(i, v.size())cin >> v[i];
}
template<typename T>
void coutarray(vector<T>& v) {
	rep(i, v.size()) {
		if (i > 0)cout << " "; cout << v[i];
	}
	cout << "\n";
}
ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	if (x == 0)return 0;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	int n;
	modint() :n(0) { ; }
	modint(ll m) {
		if (m < 0 || mod <= m) {
			m %= mod; if (m < 0)m += mod;
		}
		n = m;
	}
	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, ll 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)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 20;
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];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

ll gcd(ll a, ll b) {
	a = abs(a); b = abs(b);
	if (a < b)swap(a, b);
	while (b) {
		ll r = a % b; a = b; b = r;
	}
	return a;
}
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };

using mP = pair<modint, modint>;
//-----------------------------------

using speP = pair<ld, int>;
ll calc(vector<int> x, vector<int> y, vector<ll> p) {
	int n = x.size();
	vector<speP> vp;
	rep(i, n) {
		ld t = atan2l(y[i], x[i]);
		if (t <= 0) {
			vp.push_back({ atan2l(-y[i],-x[i]),-(i+1) });
		}
		else {
			vp.push_back({ t,i+1 });
		}
	}
	sort(all(vp));
	vector<ll> le(n + 1, INF);
	vector<ll> ri(n + 1, INF);
	rep(i, vp.size()) {
		int id = vp[i].second;
		le[i + 1] = le[i];
		if (id > 0) {
			id--;
			chmin(le[i + 1], p[id]);
		}
	}
	per(i, vp.size()) {
		int id = vp[i].second;
		ri[i] = ri[i + 1];
		if (id > 0) {
			id--;
			chmin(ri[i], p[id]);
		}
	}
	ll res = INF;
	rep(i, vp.size()) {
		int l = i;
		while (i + 1 < vp.size() && vp[i].first == vp[i + 1].first)i++;
		Rep1(j, l, i) {
			int id = vp[j].second;
			if (id < 0) {
				id = -id; id--;
				ll val = le[l] + ri[i + 1];
				chmin(res, val + p[id]);
			}
		}
	}
	return res;
}
void solve() {
	int n; cin >> n;
	vector<int> x(n), y(n);
	vector<ll> p(n);
	rep(i, n)cin >> x[i] >> y[i] >> p[i];
	//exclude (0,0)
	{
		vector<int> nx, ny;
		vector<ll> np;
		rep(i, n) {
			if (x[i] == 0 && y[i] == 0) {
				continue;
			}
			nx.push_back(x[i]);
			ny.push_back(y[i]);
			np.push_back(p[i]);
		}
		swap(x, nx); swap(y, ny); swap(p, np);
		n = x.size();
	}
	//exclude gcd
	rep(i, n) {
		int g = gcd(x[i], y[i]);
		x[i] /= g;
		y[i] /= g;
	}
	ll ans = calc(x, y, p);
	//cout << ans << "\n";
	rep(i, n) {
		x[i] *= -1;
		y[i] *= -1;
	}
	ans = min(ans, calc(x, y, p));
	if (ans == INF)ans = -1;
	cout << ans << "\n";
}


signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(10);
	//init_f();
	//init();
	//while(true)
	//expr();
	//int t; cin >> t; rep(i, t)
	solve();
	return 0;
}
accuracy: 0.7965116279069767
time_ms: 130
memory_kb: 33804
final_rank: 11

code_snippet: #pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#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<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
#include<chrono>
using namespace std;

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

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;

#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;

template<typename T>
void chmin(T& a, T b) {
	a = min(a, b);
}
template<typename T>
void chmax(T& a, T b) {
	a = max(a, b);
}
template<typename T>
void cinarray(vector<T>& v) {
	rep(i, v.size())cin >> v[i];
}
template<typename T>
void coutarray(vector<T>& v) {
	rep(i, v.size()) {
		if (i > 0)cout << " "; cout << v[i];
	}
	cout << "\n";
}
ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	if (x == 0)return 0;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	int n;
	modint() :n(0) { ; }
	modint(ll m) {
		if (m < 0 || mod <= m) {
			m %= mod; if (m < 0)m += mod;
		}
		n = m;
	}
	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, ll 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)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 20;
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];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

ll gcd(ll a, ll b) {
	a = abs(a); b = abs(b);
	if (a < b)swap(a, b);
	while (b) {
		ll r = a % b; a = b; b = r;
	}
	return a;
}
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };

using mP = pair<modint, modint>;
//-----------------------------------

using speP = pair<ld, int>;
ll calc(vector<int> x, vector<int> y, vector<ll> p) {
	int n = x.size();
	vector<speP> vp;
	rep(i, n) {
		ld t = atan2l(y[i], x[i]);
		if (t <= 0) {
			vp.push_back({ t + pi,-(i+1) });
		}
		else {
			vp.push_back({ t,i+1 });
		}
	}
	sort(all(vp));
	vector<ll> le(n + 1, INF);
	vector<ll> ri(n + 1, INF);
	rep(i, vp.size()) {
		int id = vp[i].second;
		le[i + 1] = le[i];
		if (id > 0) {
			id--;
			chmin(le[i + 1], p[id]);
		}
	}
	per(i, vp.size()) {
		int id = vp[i].second;
		ri[i] = ri[i + 1];
		if (id > 0) {
			id--;
			chmin(ri[i], p[id]);
		}
	}
	ll res = INF;
	rep(i, vp.size()) {
		int l = i;
		while (i + 1 < vp.size() && vp[i].first == vp[i + 1].first)i++;
		Rep1(j, l, i) {
			int id = vp[j].second;
			if (id < 0) {
				id = -id; id--;
				ll val = le[l] + ri[i + 1];
				chmin(res, val + p[id]);
			}
		}
	}
	return res;
}
void solve() {
	int n; cin >> n;
	vector<int> x(n), y(n);
	vector<ll> p(n);
	rep(i, n)cin >> x[i] >> y[i] >> p[i];
	//exclude (0,0)
	{
		vector<int> nx, ny;
		vector<ll> np;
		rep(i, n) {
			if (x[i] == 0 && y[i] == 0) {
				continue;
			}
			nx.push_back(x[i]);
			ny.push_back(y[i]);
			np.push_back(p[i]);
		}
		swap(x, nx); swap(y, ny); swap(p, np);
		n = x.size();
	}
	//exclude gcd
	rep(i, n) {
		int g = gcd(x[i], y[i]);
		x[i] /= g;
		y[i] /= g;
	}
	ll ans = calc(x, y, p);
	//cout << ans << "\n";
	rep(i, n) {
		x[i] *= -1;
		y[i] *= -1;
	}
	ans = min(ans, calc(x, y, p));
	if (ans == INF)ans = -1;
	cout << ans << "\n";
}


signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(10);
	//init_f();
	//init();
	//while(true)
	//expr();
	//int t; cin >> t; rep(i, t)
	solve();
	return 0;
}
accuracy: 0.29651162790697677
time_ms: 120
memory_kb: 34148
final_rank: 14

code_snippet: #pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#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<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
#include<chrono>
using namespace std;

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

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;

#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;

template<typename T>
void chmin(T& a, T b) {
	a = min(a, b);
}
template<typename T>
void chmax(T& a, T b) {
	a = max(a, b);
}
template<typename T>
void cinarray(vector<T>& v) {
	rep(i, v.size())cin >> v[i];
}
template<typename T>
void coutarray(vector<T>& v) {
	rep(i, v.size()) {
		if (i > 0)cout << " "; cout << v[i];
	}
	cout << "\n";
}
ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	if (x == 0)return 0;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	int n;
	modint() :n(0) { ; }
	modint(ll m) {
		if (m < 0 || mod <= m) {
			m %= mod; if (m < 0)m += mod;
		}
		n = m;
	}
	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, ll 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)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 20;
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];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

ll gcd(ll a, ll b) {
	a = abs(a); b = abs(b);
	if (a < b)swap(a, b);
	while (b) {
		ll r = a % b; a = b; b = r;
	}
	return a;
}
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };

using mP = pair<modint, modint>;
//-----------------------------------

using speP = pair<ld, int>;
ll calc(vector<int> x, vector<int> y, vector<ll> p) {
	int n = x.size();
	vector<speP> vp;
	rep(i, n) {
		ld t = atan2l(y[i], x[i]);
		if (t <= 0) {
			vp.push_back({ t + pi,-i });
		}
		else {
			vp.push_back({ t,i });
		}
	}
	sort(all(vp));
	vector<ll> le(n + 1, INF);
	vector<ll> ri(n + 1, INF);
	rep(i, vp.size()) {
		int id = vp[i].second;
		le[i + 1] = le[i];
		if (id >= 0) {
			chmin(le[i + 1], p[id]);
		}
	}
	per(i, vp.size()) {
		int id = vp[i].second;
		ri[i] = ri[i + 1];
		if (id >= 0) {
			chmin(ri[i], p[id]);
		}
	}
	ll res = INF;
	rep(i, vp.size()) {
		int l = i;
		while (i + 1 < vp.size() && vp[i].first == vp[i + 1].first)i++;
		Rep1(j, l, i) {
			int id = vp[j].second;
			if (id < 0) {
				ll val = le[l] + ri[i + 1];
				chmin(res, val + p[-id]);
			}
		}
	}
	return res;
}
void solve() {
	int n; cin >> n;
	vector<int> x(n), y(n);
	vector<ll> p(n);
	rep(i, n)cin >> x[i] >> y[i] >> p[i];
	//exclude (0,0)
	{
		vector<int> nx, ny;
		vector<ll> np;
		rep(i, n) {
			if (x[i] == 0 && y[i] == 0) {
				continue;
			}
			nx.push_back(x[i]);
			ny.push_back(y[i]);
			np.push_back(p[i]);
		}
		swap(x, nx); swap(y, ny); swap(p, np);
		n = x.size();
	}
	//exclude gcd
	rep(i, n) {
		int g = gcd(x[i], y[i]);
		x[i] /= g;
		y[i] /= g;
	}
	ll ans = calc(x, y, p);
	rep(i, n) {
		x[i] *= -1;
		y[i] *= -1;
	}
	ans = min(ans, calc(x, y, p));
	if (ans == INF)ans = -1;
	cout << ans << "\n";
}


signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(10);
	//init_f();
	//init();
	//while(true)
	//expr();
	//int t; cin >> t; rep(i, t)
	solve();
	return 0;
}
accuracy: 0.28488372093023256
time_ms: 130
memory_kb: 34152
final_rank: 15

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
//#define EPS 0.000000001
using namespace std;


#define EPS 0.0000000001 //★★注意★★
#define SIZE 200005

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	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 a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{
		return x != p.x? x < p.x: y < p.y;
	}

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

   	/*
	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}*/

	double x,y;
};


struct Data{

	ll X,Y,p;
};

struct Info{

	ll min_P,min_index_L,min_index_R;
	double rad_L,rad_R;
};

struct Slope{
	Slope(ll arg_dx,ll arg_dy){
		dx = arg_dx;
		dy = arg_dy;
	}
	bool operator<(const struct Slope &arg) const{
		if(dx != arg.dx){

			return dx < arg.dx;
		}else{

			return dy < arg.dy;
		}
	}
	bool operator==(const struct Slope &arg) const{

		return dx == arg.dx && dy == arg.dy;
	}
	ll dx,dy;
};

struct Node{
	Node(double arg_rad,ll arg_P){
		rad = arg_rad;
		P = arg_P;
	}
	bool operator<(const struct Node &arg) const{

		return rad < arg.rad;
	}
	double rad;
	ll P;
};

ll N;
map<pair<ll,ll>,ll> MAP;
Data D[SIZE];
vector<Slope> SLOPE;
Info info[6*SIZE];
vector<Node> V;


void init(int first_N){
	while(N < first_N)N *= 2;
}

//最大公約数
ll gcd(ll x,ll y){

	x = abs(x);
	y = abs(y);

	if(x < y){
		swap(x,y);
	}
	if(y == 0){
		return x;
	}else{
		return gcd(y,x%y);
	}
}

void update(ll loc,ll value,double rad){
	loc += N-1;

	info[loc].min_P = value;
	info[loc].min_index_L = loc-(N-1);
	info[loc].min_index_R = loc-(N-1);
	info[loc].rad_L = rad;
	info[loc].rad_R = rad;

	if(N == 1)return;

	ll parent = (loc-1)/2;
	ll L,R;

	while(true){

		L = 2*parent+1,R = 2*parent+2;

		info[parent].rad_L = info[L].rad_L;
		info[parent].rad_R = info[R].rad_R;

		if(info[L].min_P == info[R].min_P){

			info[parent].min_P = info[L].min_P;
			info[parent].min_index_L = info[L].min_index_L; //★値が同じならCW方向のvectorを優先★
			info[parent].min_index_R = info[R].min_index_R; //★値が同じならCCW方向のvectorを優先★


		}else if(info[L].min_P < info[R].min_P){

			info[parent].min_P = info[L].min_P;
			info[parent].min_index_L = info[L].min_index_L;
			info[parent].min_index_R = info[L].min_index_R;

		}else{ //info[L].min_P > info[R].min_P

			info[parent].min_P = info[R].min_P;
			info[parent].min_index_L = info[R].min_index_L;
			info[parent].min_index_R = info[R].min_index_R;
		}

		if(parent == 0)break;
		else{
			parent = (parent-1)/2;
		}
	}
}

Info query(double search_L,double search_R,ll node_id,bool to_ccw){

	Info ret;

	if(info[node_id].rad_R < search_L || info[node_id].rad_L > search_R){

		ret.min_P = HUGE_NUM;

		return ret;
	}

	if(search_L <= info[node_id].rad_L && search_R >= info[node_id].rad_R){

		return info[node_id];
	}

	ll L = 2*node_id+1;
	ll R = 2*node_id+2;

	Info info_L = query(search_L,search_R,L,to_ccw);
	Info info_R = query(search_L,search_R,R,to_ccw);

	if(info_L.min_P < info_R.min_P){

		return info_L;

	}else if(info_L.min_P > info_R.min_P){

		return info_R;
	}else{ //info_L.min_P == info_R.min_P

		if(to_ccw){

			return info_R; //★★よりCCW方向へ★★
		}else{

			return info_L; //★★よりCW方向へへ★★
		}
	}
}


double calc_rad(Point p){

	if(p.y == 0){

		if(p.x > 0){

			return 0;

		}else{ //p.x < 0

			return M_PI;
		}

	}else if(p.x == 0){

		if(p.y > 0){

			return M_PI/2.0;
		}else{


			return 3*M_PI/2.0;
		}

	}else{

		double base = atan(fabs(p.y)/fabs(p.x));

		if(p.x > 0){

			if(p.y > 0){

				return base;

			}else{ //p.y < 0

				return 2*M_PI-base;
			}

		}else{ //p.x < 0

			if(p.y > 0){

				return M_PI-base;

			}else{

				return base+M_PI;
			}
		}
	}
}


int main(){

	ll first_N;

	scanf("%lld",&first_N);

	for(int i = 0; i < first_N; i++){

		scanf("%lld %lld %lld",&D[i].X,&D[i].Y,&D[i].p);

		if(D[i].X == 0 && D[i].Y == 0)continue;

		ll common = gcd(D[i].X,D[i].Y);
		D[i].X /= common;
		D[i].Y /= common;

		auto at = MAP.find(make_pair(D[i].X,D[i].Y));
		if(at == MAP.end()){

			MAP[make_pair(D[i].X,D[i].Y)] = D[i].p;
			SLOPE.push_back(Slope(D[i].X,D[i].Y));

		}else{
			ll tmp = MAP[make_pair(D[i].X,D[i].Y)];
			if(D[i].p < tmp){

				MAP[make_pair(D[i].X,D[i].Y)] = D[i].p;
			}
		}
	}

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


	for(int i = 0; i < SLOPE.size(); i++){

		double tmp_rad = calc_rad(Point(SLOPE[i].dx,SLOPE[i].dy));
		ll tmp_P = MAP[make_pair(SLOPE[i].dx,SLOPE[i].dy)];
		V.push_back(Node(tmp_rad,tmp_P));
	}

	sort(V.begin(),V.end());

	N = 1;
	init(V.size());

	for(ll i = 0; i <= 2*N-2; i++){

		info[i].min_P = HUGE_NUM;
		info[i].rad_R = HUGE_NUM;
		info[i].rad_L = HUGE_NUM;
	}

	for(int i = 0; i < V.size(); i++){

		update(i,V[i].P,V[i].rad);
	}

	ll ans = HUGE_NUM;

	Info info_ccw,info_ccw2;
	Info info_rest,info_rest2;
	double rad_L,rad_R;

	for(int i = 0; i < V.size(); i++){

		//多分、少なくとも1つのベクトルは、あるベクトルからccw方向にπ-EPS見た際の最小ベクトルであるはず(3本で作れるなら)
		if(V[i].rad+M_PI-EPS > 2*M_PI){

			info_ccw = query(V[i].rad+EPS,2*M_PI,0,true);
			info_ccw2 = query(0.0,V[i].rad+M_PI-EPS-2*M_PI,0,true);

			if(info_ccw2.min_P <= info_ccw.min_P){

				info_ccw = info_ccw2;
			}

		}else{

			info_ccw = query(V[i].rad+EPS,V[i].rad+M_PI-EPS,0,true);
		}

		if(info_ccw.min_P == HUGE_NUM){
			continue;
		}

		int index_ccw = info_ccw.min_index_R;

		rad_L = V[i].rad+M_PI+EPS;
		if(rad_L >= 2*M_PI){

			rad_L -= 2*M_PI;
		}
		rad_R = V[index_ccw].rad+M_PI-EPS;
		if(rad_R >= 2*M_PI){

			rad_R -= 2*M_PI;
		}

		if(rad_L > rad_R){ //rad == 2πの線を跨ぐ

			info_rest = query(rad_L,2*M_PI,0,true);
			info_rest2 = query(0.0,rad_R,0,true);

			info_rest.min_P = min(info_rest.min_P,info_rest2.min_P);

		}else{

			info_rest = query(rad_L,rad_R,0,true);
		}

		if(info_rest.min_P == HUGE_NUM)continue;

		ans = min(ans,V[i].P+V[index_ccw].P+V[info_rest.min_index_R].P);
	}

	//★4本でないと不可な場合あり(x,y軸のように4つのvectorが直交する場合)★
	Info info1,info2,info3,info4;

	info1 = query(0,(M_PI/2.0)-EPS,0,true);
	info2 = query(M_PI/2.0,M_PI-EPS,0,true);
	info3 = query(M_PI,(3.0*M_PI/2.0)-EPS,0,true);
	info4 = query((3.0*M_PI/2.0),2*M_PI-EPS,0,true);

	if(info1.min_P != HUGE_NUM && info2.min_P != HUGE_NUM && info3.min_P != HUGE_NUM && info4.min_P != HUGE_NUM){

		ans = min(ans,info1.min_P+info2.min_P+info3.min_P+info4.min_P);
	}

	if(ans == HUGE_NUM){

		printf("-1\n");
	}else{

		printf("%lld\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 360
memory_kb: 47236
final_rank: 6

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"

using namespace std;

constexpr long long int MOD = 1000000007;
//constexpr int MOD = 1000000007;
//constexpr int MOD = 998244353;
//constexpr long long int MOD = 998244353;
constexpr double EPS = 1e-9;

//int N, M, K, H, W, L, R;
long long int N, M, K, H, W, L, R;

int gcd(int a, int b) {
	while (b) {
		a %= b;
		swap(a, b);
	}
	return a;
}

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

	cin >> N;
	vector<long double>x(N);
	vector<long double>y(N);
	vector<long long int>p(N);
	vector<pair<long double, long long int>>v;
	map<pair<int, int>, long long int>mp;
	for (int i = 0; i < N; i++) {
		int a, b;
		cin >> a >> b >> p[i];
		if (a == 0 && b == 0)continue;
		int g = gcd(abs(a), abs(b));
		a /= g;
		b /= g;
		if (mp[{a, b}] == 0)mp[{a, b}] = MOD;
		mp[{a, b}] = min(mp[{a, b}], p[i]);
		x[i] = a, y[i] = b;
		if (x[i] || y[i]) {
			v.push_back({ atan2l(y[i], x[i]), p[i] });
		}
	}
	sort(v.begin(), v.end());
	M = v.size();
	long double pi = acosl(-1);
	for (int i = 0; i < M; i++) {
		v.push_back({ v[i].first + pi * 2,v[i].second });
	}
	for (int i = 0; i < M; i++) {
		v.push_back({ v[i].first + pi * 4,v[i].second });
	}
	long long int ret = MOD * MOD;
	for(int loop=0;loop<2;loop++){
		set<pair<long long int, int>>fst;
		set<pair<long long int, int>>snd;
		int a = 0, b = 0, c = 0, d = 0;
		for (int i = 1; i < M * 3; i++) {
			if (v[i].first <= v[0].first + pi / 2-EPS)a = i;
			else if (v[i].first < v[0].first + pi - EPS) {
				b = i;
				fst.insert({ v[i].second,i });
			}
			else if (v[i].first <= v[0].first + pi + EPS) {
				c = i;
			}
			else if (v[i].first <= v[0].first + pi * 3 / 2-EPS) {
				d = i;
				snd.insert({ v[i].second,i });
			}
			b = max(a, b);
			c = max(c, b);
			d = max(c, d);
		}
		a++, b++, c++, d++;
		long long int ans = MOD * MOD;
		if (!fst.empty() && !snd.empty()) {
			ans = min(ans, v[0].second + fst.begin()->first + snd.begin()->first);
		}
		for (int i = 1; i < M; i++) {
			while (v[b].first < v[i].first + pi - EPS) {
				fst.insert({ v[b].second,b });
				b++;
			}
			while (v[a].first <= v[i].first + pi / 2-EPS) {
				fst.erase({ v[a].second,a });
				a++;
			}
			while (v[d].first <= v[i].first + pi * 3 / 2-EPS) {
				snd.insert({ v[d].second,d });
				d++;
			}
			while (v[c].first <= v[i].first + pi + EPS) {
				snd.erase({ v[c].second,c });
				c++;
			}
			if (!fst.empty() && !snd.empty()) {
				ans = min(ans, v[i].second + fst.begin()->first + snd.begin()->first);
			}
		}
		ret = min(ret, ans);
		for (auto &i : v) {
			i.first = -i.first;
		}
		reverse(v.begin(), v.end());
	}
	vector<long long int>pa;
	for (auto i : mp) {
		if (i.first.second <= 0 && !(i.first.first == 1 && i.first.second == 0)) {
			if (mp.find({ -i.first.first,-i.first.second }) != mp.end()) {
				pa.push_back(i.second + mp[{-i.first.first, -i.first.second}]);
			}
		}
	}
	sort(pa.begin(), pa.end());
	if (pa.size() > 1) {
		ret = min(ret, pa[0] + pa[1]);
	}
	if (ret == MOD * MOD)ret = -1;
	cout << ret << endl;
}
accuracy: 1
time_ms: 720
memory_kb: 60768
final_rank: 8

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"

using namespace std;

constexpr long long int MOD = 1000000007;
//constexpr int MOD = 1000000007;
//constexpr int MOD = 998244353;
//constexpr long long int MOD = 998244353;
constexpr double EPS = 1e-9;

//int N, M, K, H, W, L, R;
long long int N, M, K, H, W, L, R;


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

	cin >> N;
	vector<long double>x(N);
	vector<long double>y(N);
	vector<long long int>p(N);
	vector<pair<long double, long long int>>v;
	for (int i = 0; i < N; i++) {
		cin >> x[i] >> y[i] >> p[i];
		if (x[i] || y[i]) {
			v.push_back({ atan2l(y[i], x[i]), p[i] });
		}
	}
	sort(v.begin(), v.end());
	M = v.size();
	long double pi = acosl(-1);
	for (int i = 0; i < M; i++) {
		v.push_back({ v[i].first + pi * 2,v[i].second });
	}
	for (int i = 0; i < M; i++) {
		v.push_back({ v[i].first + pi * 4,v[i].second });
	}
	long long int ret = MOD * MOD;
	{
		set<pair<long long int, int>>fst;
		set<pair<long long int, int>>snd;
		int a = 0, b = 0, c = 0, d = 0;
		for (int i = 1; i < M * 3; i++) {
			if (v[i].first <= v[0].first + pi / 2-EPS)a = i;
			else if (v[i].first < v[0].first + pi - EPS) {
				b = i;
				fst.insert({ v[i].second,i });
			}
			else if (v[i].first <= v[0].first + pi + EPS) {
				c = i;
			}
			else if (v[i].first <= v[0].first + pi * 3 / 2-EPS) {
				d = i;
				snd.insert({ v[i].second,i });
			}
			b = max(a, b);
			c = max(c, b);
			d = max(c, d);
		}
		a++, b++, c++, d++;
		long long int ans = MOD * MOD;
		if (!fst.empty() && !snd.empty()) {
			ans = min(ans, v[0].second + fst.begin()->first + snd.begin()->first);
		}
		for (int i = 1; i < M; i++) {
			while (v[b].first < v[i].first + pi - EPS) {
				fst.insert({ v[b].second,b });
				b++;
			}
			while (v[a].first <= v[i].first + pi / 2-EPS) {
				fst.erase({ v[a].second,a });
				a++;
			}
			while (v[d].first <= v[i].first + pi * 3 / 2-EPS) {
				snd.insert({ v[d].second,d });
				d++;
			}
			while (v[c].first <= v[i].first + pi + EPS) {
				snd.erase({ v[c].second,c });
				c++;
			}
			if (!fst.empty() && !snd.empty()) {
				ans = min(ans, v[i].second + fst.begin()->first + snd.begin()->first);
			}
		}
		ret = min(ret, ans);
	}
	for (auto &i : v) {
		i.first = -i.first;
	}
	reverse(v.begin(), v.end());
	{
		set<pair<long long int, int>>fst;
		set<pair<long long int, int>>snd;
		int a = 0, b = 0, c = 0, d = 0;
		for (int i = 1; i < M * 3; i++) {
			if (v[i].first <= v[0].first + pi / 2-EPS)a = i;
			else if (v[i].first < v[0].first + pi - EPS) {
				b = i;
				fst.insert({ v[i].second,i });
			}
			else if (v[i].first <= v[0].first + pi + EPS) {
				c = i;
			}
			else if (v[i].first <= v[0].first + pi * 3 / 2-EPS) {
				d = i;
				snd.insert({ v[i].second,i });
			}
			b = max(a, b);
			c = max(c, b);
			d = max(c, d);
		}
		a++, b++, c++, d++;
		long long int ans = MOD * MOD;
		if (!fst.empty() && !snd.empty()) {
			ans = min(ans, v[0].second + fst.begin()->first + snd.begin()->first);
		}
		for (int i = 1; i < M; i++) {
			while (v[b].first < v[i].first + pi - EPS) {
				fst.insert({ v[b].second,b });
				b++;
			}
			while (v[a].first <= v[i].first + pi / 2-EPS) {
				fst.erase({ v[a].second,a });
				a++;
			}
			while (v[d].first <= v[i].first + pi * 3 / 2-EPS) {
				snd.insert({ v[d].second,d });
				d++;
			}
			while (v[c].first <= v[i].first + pi + EPS) {
				snd.erase({ v[c].second,c });
				c++;
			}
			if (!fst.empty() && !snd.empty()) {
				ans = min(ans, v[i].second + fst.begin()->first + snd.begin()->first);
			}
		}
		ret = min(ret, ans);
	}
	if (ret == MOD * MOD)ret = -1;
	cout << ret << endl;
}
accuracy: 0.7965116279069767
time_ms: 580
memory_kb: 43880
final_rank: 13