Pagini recente » Cod sursa (job #2139399) | Cod sursa (job #2371694) | Cod sursa (job #3282796) | Cod sursa (job #1731622) | Cod sursa (job #2703004)
#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); }
vector<vector<int>> ComputeFaces(vector<Point>& P, auto& graph) {
int n = graph.size(), piv;
auto cmp = [&](int a, int b) {
Point p = P[a] - P[piv], q = P[b] - P[piv];
return make_pair(half(p), p.imag() * q.real()) <
make_pair(half(q), p.real() * q.imag());
};
vector<vector<int>> which(n);
for (int i = 0; i < n; ++i) {
piv = i; sort(graph[i].begin(), graph[i].end(), cmp);
which[i].assign(graph[i].size(), -1);
}
vector<vector<int>> faces;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < (int)graph[i].size(); ++j) {
if (which[i][j] != -1) continue;
vector<int> face;
int ci = i, cj = j;
do {
assert(which[ci][cj] == -1);
face.push_back(ci);
int ni = graph[ci][cj], nj;
piv = ni; nj = lower_bound(graph[ni].begin(),
graph[ni].end(), ci, cmp) - graph[ni].begin();
assert(graph[ni][nj] == ci);
if (++nj == (int)graph[ni].size()) nj = 0;
which[ci][cj] = faces.size(); ci = ni; cj = nj;
} while (ci != i);
assert(cj == j);
faces.emplace_back(move(face));
}
}
// Can also return `which`, anthough keep in mind that
// the graph gets shuffled.
return faces;
}
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);
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);
}
auto faces = ComputeFaces(P, graph);
int f = faces.size();
vector<vector<int>> dual(f);
vector<int> deg(f, 0);
map<pair<int, int>, int> e2f;
for (int i = 0; i < f; ++i) {
int l = faces[i].size();
for (int j = 0, k = l - 1; j < l; k = j++) {
e2f[make_pair(faces[i][k], faces[i][j])] = i;
}
}
for (int i = 0; i < f; ++i) {
int l = faces[i].size();
for (int j = 0, k = l - 1; j < l; k = j++) {
dual[i].push_back(e2f[make_pair(faces[i][j], faces[i][k])]);
}
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 < n; ++i)
for (auto j : graph[i]) {
int df = col[e2f[make_pair(i, j)]] - col[e2f[make_pair(j, i)]];
if (df > 0) cout << i + 1 << " " << j + 1 << " " << df << '\n';
}
return 0;
}