Pagini recente » Cod sursa (job #2517254) | Cod sursa (job #1944663) | Cod sursa (job #2321741) | Cod sursa (job #1334649) | Cod sursa (job #2703018)
#ifdef LOCAL
#include <debug.hpp>
#else
#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,tune=native")
#define debug(...)
#endif
#include <bits/stdc++.h>
using namespace std;
using Point = complex<double>;
int half(Point p) { return p.imag() < 0 || (p.imag() == 0 && p.real() < 0); }
double cross(Point p, Point q) { return p.real() * q.imag() - p.imag() * q.real(); }
struct Edge { int face, origin, nxt, prv; };
vector<Edge> ComputeFaces(vector<Point>& P, vector<pair<int, int>>& E) {
int n = P.size(), m = E.size();
for (int i = 0; i < m; ++i) {
Point p = P[E[i].second] - P[E[i].first];
if (half(p)) swap(E[i].first, E[i].second);
}
vector<int> order(m);
iota(order.begin(), order.end(), 0);
sort(order.begin(), order.end(), [&](int a, int b) {
Point p = P[E[a].second] - P[E[a].first];
Point q = P[E[b].second] - P[E[b].first];
return cross(p, q) > 0;
});
order.resize(2 * m);
for (int i = 0; i < m; ++i) {
order[i + m] = 2 * order[i] + 1;
order[i] = 2 * order[i];
}
vector<int> fst(n, -1), lst(n, -1), nxt(2 * m, -1);
vector<Edge> ret(2 * m);
for (auto i : order) {
int a = (i % 2 ? E[i / 2].second : E[i / 2].first);
ret[i].origin = a;
ret[i].face = -1;
if (fst[a] == -1) fst[a] = i;
else ret[lst[a]].nxt = i;
lst[a] = i;
}
for (int i = 0; i < n; ++i)
ret[lst[i]].nxt = fst[i];
for (int i = 0; i < 2 * m; ++i) {
if (i % 2 == 0) swap(ret[i].nxt, ret[i + 1].nxt);
ret[ret[i].nxt].prv = i;
}
int f = 0;
for (int i = 0; i < 2 * m; ++i) {
if (ret[i].face == -1) {
for (int j = i; ret[j].face == -1; j = ret[j].nxt)
ret[j].face = f;
f++;
}
}
return ret;
}
int main() {
ifstream cin("nowhere-zero.in");
ofstream cout("nowhere-zero.out");
int n, m; cin >> n >> m;
vector<Point> P(n);
for (int i = 0; i < n; ++i) {
double x, y; cin >> x >> y;
P[i] = {x, y};
}
vector<vector<int>> graph(n);
vector<pair<int, int>> E;
for (int i = 0; i < m; ++i) {
int a, b; cin >> a >> b; --a; --b;
graph[a].push_back(b);
graph[b].push_back(a);
E.emplace_back(a, b);
}
auto L = ComputeFaces(P, E);
int f = 0;
for (auto x : L) f = max(f, x.face + 1);
vector<vector<int>> dual(f);
for (int i = 0; i < 2 * m; ++i)
dual[L[i].face].push_back(L[i ^ 1].face);
vector<int> deg(f, 0);
for (int i = 0; i < f; ++i) {
sort(dual[i].begin(), dual[i].end());
dual[i].erase(unique(dual[i].begin(), dual[i].end()), dual[i].end());
deg[i] = dual[i].size();
}
vector<int> q;
for (int i = 0; i < f; ++i)
if (deg[i] <= 5)
q.push_back(i);
for (int i = 0; i < f; ++i) {
int node = q[i];
for (auto vec : dual[node]) {
if (--deg[vec] == 5)
q.push_back(vec);
}
}
reverse(q.begin(), q.end());
vector<int> col(f, -1);
for (auto node : q) {
int bad = 0;
for (auto vec : dual[node]) {
if (col[vec] != -1)
bad |= (1 << col[vec]);
}
col[node] = 0;
while (bad & (1 << col[node]))
++col[node];
}
for (int i = 0; i < 2 * m; ++i) {
int df = col[L[i].face] - col[L[i^1].face];
if (df > 0)
cout << L[i].origin + 1 << " " << L[i^1].origin + 1 << " " << df << '\n';
}
return 0;
}